集合是java中提供的一种容器,可以用来存储多个数据。
集合和数组的不同之处:
集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map。
单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.List和java.util.Set。其中,
List的特点是元素有序、元素可重复
Set的特点是元素无序,而且不可重复。
List接口的主要实现类有java.util.ArrayList、java.util.LinkedList和java.util.Vector
Set接口的主要实现类有java.util.HashSet和java.util.TreeSet
List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
List接口特点:
1.是一个元素存取有序的集合。
2.是一个带有索引的集合,通过索引就可以精确的操作集合中的元素。
3.集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。List接口中常用方法:List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法:
public void add(int index,E element):将指定的元素,添加到该集合中的指定位置上。
public E get(int index):返回集合中指定位置的元素。
public E remove(int index):移除列表中指定位置的元素,返回的是被移除的元素。
public E set(int index,E element):用指定元素替换集合中指定位置的元素,返回值为更新前的元素。
默认初始容量为10,如果超过10,那么它会自动扩容:当前容量*1.5
适合随机查找和遍历,不适合插入和删除。
常用方法:
add(E e) 将指定的元素追加到此列表的末尾。
add(int index,E element)在此列表中的指定位置插入指定的元素。
contains(Object o)如果此列表包含指定的元素,则返回true。
get(int index)返回此列表中指定位置的元素。
isEmpty()如果此列表不包含元素,则返回true。
remove(int index)删除该列表中指定位置的元素。
set(int index,E element)用指定的元素替换此列表中指定位置的元素。
size()返回此列表中的元素数
ArrayList遍历方法代码:
package com.yyh.collection.list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: Santo
* Date: 2022/03/16 10:31
* Description:
* Version: V1.0
*/
public class ForArrayListLinkedList {
public static void main(String[] args) {
//多态定义方式
List arrayList = new ArrayList();
arrayList.add(3);
arrayList.add(27);
arrayList.add(34);
arrayList.add(7);
arrayList.add(7);
arrayList.add(12);
// for (int i = 0; i < arrayList.size() ; i++) {
// System.out.println(arrayList.get(i));
// if (Integer.parseInt(arrayList.get(i).toString()) == 7){
// break;
// }
// }
System.out.println(arrayList);
System.out.println("——————————————————————————————");
//需求:循环遍历,找元素是7,找到就将其移除。
//两种解决方法:第一种:for循环中增量直接递减一次。第二种:采用迭代器——推荐使用
//第一种方法:采用for循环
// for (int i = 0; i < arrayList.size() ; i++) {
// if (Integer.parseInt(arrayList.get(i).toString()) == 7){
// arrayList.remove(i);
i--; //解决方法一
// }
// }
// System.out.println(arrayList);
//第二种方法:采用迭代器方式遍历集合
Iterator it = arrayList.iterator();//以正确的顺序返回该列表中的元素的迭代器
while(it.hasNext()){ //如果迭代器中还有更多的元素,则返回true
//返回迭代中的下一个元素
if (Integer.parseInt(it.next().toString()) == 7){
//移除元素
it.remove();
}
}
System.out.println(arrayList);
}
}
LinkedList是一个双向链表
实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。
public void addFirst(E e):将指定元素插入此列表的开头
public void addLast(E e):将指定元素添加到此列表的结尾
public E getFirst():返回此列表的第一个元素
public E getLast():返回此列表的最后一个元素
public E removeFirst/Last():移除并返回此列表的第一个或者最后一个元素
public E pop():从此列表所表示的堆栈处弹出一个元素
public void push(E e):将元素推入此列表所表示的堆栈
public boolean isEmpty(): 如果列表 不包含元素,则返回true
Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问Arraylist慢。
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.Iterator。Iterator接口也是java集合中的一员,但它与Collection、Map接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。
Iterator接口的常用方法如下:
public E next():返回迭代的下一个元素
public boolean hasNext():如果仍有元素可以迭代,则返回true。
代码演示:
List arrayList = new ArrayList();
arrayList.add(3);
arrayList.add(27);
arrayList.add(34);
arrayList.add(7);
arrayList.add(7);
arrayList.add(12);
Iterator it = arrayList.iterator();//以正确的顺序返回该列表中的元素的迭代器
while(it.hasNext()){ //如果迭代器中还有更多的元素,则返回true
//返回迭代中的下一个元素
if (Integer.parseInt(it.next().toString()) == 7){
//移除元素
it.remove();
}
}
System.out.println(arrayList);
java.util.Set接口和java.util.List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格了。与List接口不同的是,Set接口中元素无序,没有索引的方法,也不支持普通的for循环遍历,并且都会以某种规则保证存入的元素不出现重复。
特点:
Set接口重要的子类:java.util.HashSet、java.util.TreeSet
掌握重要方法,原理:hashCode、equals
哈希值:哈希值就是一个十进制的整数,就是操作系统随机分配值(也可以理解成对象的地址值,逻辑上的地址值,并不是真正的物理地址。注意:哈希值是模拟的)
int hashCode() 返回对象的哈希码值
在jdk1.8之前:HashSet底层机构采用的是哈希表中(数组+链表)
在jdk1.8之后,采用(数组+链表+红黑树)的结构
HashSet通过hashCode值来确定元素在内存中的位置,一个hashCode位置上可以存放多个元素。
根据hash值和equals两个条件判断是否是同一个元素,不是则添加入hashSet中。
给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一。
定义User类,重写hashCode和equals方法,存入HashSet中:
package com.yyh.collection.set;
import java.util.Objects;
/**
* Created with IntelliJ IDEA.
* User: Santo
* Date: 2022/03/16 20:49
* Description:
* Version: V1.0
*/
public class User extends Object implements Comparable{
private String username;
private String password;
private double money;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(username, user.username) &&
Objects.equals(password, user.password);
}
@Override
public int hashCode() {
return Objects.hash(username, password);
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public User(String username, String password, double money) {
this.username = username;
this.password = password;
this.money = money;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", money=" + money +
'}';
}
// 对TreeSet对象排列,重写compareTo()
@Override
public int compareTo(Object o) {
User o2 = (User)o;
if(this.getMoney() > o2.getMoney()){
return 1;
}
if(this.getMoney() < o2.getMoney()){
return -1;
}
return 0;
}
}
存入HashSet中:
package com.yyh.collection.set;
import java.util.HashSet;
/**
* Created with IntelliJ IDEA.
* User: Santo
* Date: 2022/03/17 16:59
* Description:
* Version: V1.0
*/
public class MyHashSetExample01 {
public static void main(String[] args) {
User user1 =new User("zhangsan","123");
User user2 =new User("zhangsan","123");
System.out.println(user1.hashCode());
System.out.println(user2.hashCode());
System.out.println(user1.equals(user2 ));
HashSet<User> hashSet = new HashSet<User>();
hashSet.add(user1);
hashSet.add(user2);
System.out.println(hashSet);
}
}
package com.yyh.collection.set;
import java.util.Comparator;
import java.util.HashSet;
import java.util.TreeSet;
/**
* Created with IntelliJ IDEA.
* User: Santo
* Date: 2022/03/17 17:12
* Description:
* Version: V1.0
*/
public class TreeSetExample01 {
public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet();
//默认自然排序机制,与HashSet不同
treeSet.add(1);
treeSet.add(7);
treeSet.add(4);
treeSet.add(3);
treeSet.add(9);
treeSet.add(2);
System.out.println(treeSet);
//默认情况,TreeSet中不能直接存放对象,要想存放对象需要进行对象排序规则编写。
//1.内部类方式实现Comparator,2.实现接口Comparable
//方法一:内部类方法
// User user1 =new User("zhangsan","123",1000);
// User user2 =new User("zhangsan","123",2000);
// TreeSet treeSet2 = new TreeSet(new Comparator() {
// @Override
// public int compare(User o1, User o2) {//自己制定排序的规则,返回值需要参考API
// if(o1.getMoney() > o2.getMoney()){
// return 1;
// }
// if(o1.getMoney() < o2.getMoney()){
// return -1;
// }
// return 0;
// }
// });
// treeSet2.add(user1);
// treeSet2.add(user2);
// System.out.println(treeSet2);
// 方法二:修改User中的compareTo方法:(User代码在上面)
User user1 =new User("zhangsan","123",1000);
User user2 =new User("zhangsan","123",2000);
TreeSet<User> treeSet2 = new TreeSet<User>();
treeSet2.add(user1);
treeSet2.add(user2);
System.out.println(treeSet2);
}
}
java提供了专门的集合类用来存放映射关系的对象,即java.util.Map接口。
Collection中的集合,元素是孤立存在的,向集合中存储元素采用一个个元素的方式存储。Map中的集合,元素是成对存在的,每个元素由键与值两部分组成,通过键可以找到所对应的值。Collection中的集合称为单列集合,Map中的集合称为双列集合。需要注意的是Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
通过查看Map接口描述,可以看到Map有多个子类,例:HashMap集合、TreeMap集合、Hashtable集合、LinkedHashMap集合。
HashMap存储自定义类型键值,键值对方式:即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。
在HashMap中存放元素key原理和HashSet一致,如果key重复,value值覆盖重复元素。
put(K key, V value) 添加元素
get(Object key) 获取key对应的value值
keySet() 返回此地map中包含的键的Set视图
特点:
HashMap的几种遍历方式:
package com.yyh.map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Created with IntelliJ IDEA.
* User: Santo
* Date: 2022/03/18 15:22
* Description:
* Version: V1.0
*/
public class HashMapExample01 {
public static void main(String[] args) {
HashMap<String,Object> hashMap = new HashMap<String,Object>();
//添加元素
hashMap.put("key01","张三");
hashMap.put("key02","李四");
hashMap.put("key03","王五");
hashMap.put("key04","王五");
hashMap.put("key05","王五");
System.out.println(hashMap);
System.out.println(hashMap.get("key03"));
//HashMap几种遍历方法:
// 1.迭代器得到String,keySet方法返回此地图中包含的Set视图
// Set set = hashMap.keySet();
// Iterator it = set.iterator();
// while(it.hasNext()){
// System.out.println(it.next());
// }
// 2.通过foreach方式得到两个值
// Set sets = hashMap.keySet();
// for (String key:sets
// ) {
// System.out.println(key+"="+hashMap.get(key));
// }
//3.遍历Set>,entrySet返回此地图中包含的映射的Set视图
Set<Map.Entry<String, Object>> entrySet = hashMap.entrySet();
for (Map.Entry<String,Object> map:entrySet
) {
String key = map.getKey();
Object value = map.getValue();
System.out.println(key+"="+value);
}
}
}
TreeMap中key存储原理和TreeSet是一样的
TreeMap中键不允许为null,值可以为null
特点:
Hashtable底层机构,原理,方法和HashMap大致相同
和HashMap不同点:1.Hashtable是线程安全的,HashMap是非线程安全。2.Hashtable效率低,HashMap效率高,常规开发中基本使用HashMap。3.键值都不允许为null。
HashMap下的子类,是链表和哈希表组合的一个数据存储结构,有序并且速度快。
特点:
Collection虽然可以存储各种对象,但实际上通常Collection只存储同一类型对象。
泛型:可以在类或方法中预支地使用未知的类型。一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。
使用泛型的好处:将运行十七的ClassCastException,转移到了编译时期变成了编译失败。避免了类型强转的麻烦。
泛型的定义与使用:泛型用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。
定义格式:
修饰符 class 类名<代表泛型的变量>{ }
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
interface 接口名<代表泛型的变量>{ }
此类仅有静态方法组合或返回集合。包含对集合进行操作的多态算法,“包装器”,返回由指定集合支持的新集合,以及其他一些可能的和最终的。