公众号:菜鸡干Java 站点:https://www.maliaoblog.cn
集合介绍
Java集合类是一种特别的工具类,可以储存对象,并实现了常用的数据结构,另外还能保存具有映射关系的关联数组。集合大致分为Set
,List
,Queue
,Map
四种,其中Set
代表无序、不可重复,List
代表有序、重复,Map
则代表具有映射关系,Java5增加了Queue
集合,代表一种队列集合实现。Java集合就像一种容器,把多个对象放到容器中。Java5之前,J集合会丢失对象的数据类型,把所有对象都当成Object
类型,从Java5开始增加了泛型,集合可以记住容器中对象的数据类型,从而能编写更简洁的代码。
所有的集合类都位于java.util
包下,后来在java.util.concurrent
包下提供了多线程集合类。集合类和数组不太一样,数组元素可以是基本数据类型,也可以是对象;而集合只能保存对象(实际保存的是对象的引用变量)。集合类主要由两个接口来实现,Collection
和Map
,两个根接口。
上图有Map
接口的众多实现类,这些类在功能、用法上存在一定的差异,但它们都有一个功能特征,保存的每项数据是Key-value
键值对。Map
的Key
是不可重复的,key
用于标识集合集合里的每项数据,如果要查数据,根据Key
来获取。添加一个对象到集合中,Set
集合无法记住这个元素的顺序,系统无法识别,所以Set
里的元素不能重复。
对于这四种集合,其中常用的有:HashSet、TreeSet、ArrayList、ArrayDeque、LinkedList、HashMap和TreeMap等实现类。
Collection和Iterator接口
Collection接口是List
,Set
,Queue
接口的父接口,如果接口没弄明白,可以看看之前的文章Java的异常、多态要点及抽象类和接口。Collection接口定义了如下方法:
boolean add(Object o) | 向集合里添加一个元素,如果添加成功则返回true |
---|---|
boolean addAll(Collection c) | 把集合内元素添加到指定集合,成功返回true |
void clear() | 清除集合内所有元素,将集合长度变为0 |
boolean contains(Object o) | 返回集合是否包含指定元素 |
boolean containsAll(Collection c) | 返回集合是否包含集合c所有元素 |
boolean isEmpty() | 返回集合是否为空,长度为0返回true |
Iterator iterator() | 返回一个Iterator对象用于遍历 |
boolean remove(Object o) | 删除指定元素o,如果有多个删除第一个 |
boolean retainAll(Collection c) | 从集合中删除集合c里不包含的元素,相当于求和集合c的交集 |
int size() | 返回集合里元素个数 |
Object[] toArray() | 将一个集合转换成数组 |
boolean remove(Collection c) | 从集合中删除集合c里包含的元素 |
具体可阅读API文档,里面有详细信息。编译时可能会输出一些警告,提醒没有使用泛型来限制集合内元素类型,不过之后会提到泛型编程。当使用System.out
的println
方法来输出集合对象时,将输出[e1,e2...]
形式,这是因为所有Collection
实现类重写了toString
方法,该方法可一次性输出集合中所有元素。如果想依次访问集合中的每一个元素,则需要使用某种遍历方法。
集合的遍历
一、Lambda表达式遍历
Java8为Iterable
接口新增了一个forEach
方法,参数类型是一个函数式接口,而Iterable
接口是Collection
接口的父接口,所以Collection
集合类也可以调用该方法。当调用Iterable
的forEach(Consumer a)
方法时,程序将集合元素传给Consumer
的accept(T t)
抽象方法,然后用Lambda
表达式遍历。
Collection names = new HashSet();
names.add("张三");
names.add("李四");
names.forEach(obj ->System.out.println(" "+obj));
二、Java8增强Iterator
遍历集合
Iterator
接口也是Java
集合框架的成员,但它与Collection
、Map
不一样,它们是用来放对象的,而Iterator
则用于遍历Collecton
集合中的元素,Iterator
对象也被称为迭代器
。
Iterator
接口定义了如下4种方法:
- boolean hasNext():如果没有遍历完,则返回
true
- Object next():返回集合的下一个元素,注意是
Object
对象 - void remove():删除集合上一次next方法返回的元素
- void forEachRemaining(Consumer a):Java8新增的方法,该方法可使用
Lambda
表达式遍历集合
Collection names = new HashSet();
names.add("张三");
names.add("李四");
Iterator it = names.iterator();
while(it.hasNext()){
String name = (String)it.next();
System.out.println(name);
if(name.equals("张三")){
it.remove();//names.remove(name);将报错
}//迭代时不能改变集合元素的值
}
Iterator
仅用于遍历集合,本身不提供装载对象的能力。如果要创建一个Iterator
对象,则必须要有一个被遍历的集合,没有集合那要Iterator
何用。迭代器采用快速报错fail-fast
机制,一旦检测到集合已被修改,抽象立即发出ConcurrentModificationException
异常,而不是显示修改后的结果,这样可以避免在共享资源时而引发异常问题。
三、用foreach
循环遍历集合
除了可以使用Iterator
接口迭代访问Collection
集合里元素之外,使用Java5提供的foreach
循环迭代访问更简单。
Collection names = new HashSet();
names.add("张三");
names.add("李四");
for(Objection obj : names){
String name = (String)obj;
System.out.println(name);
}
与Iterator
接口迭代集合元素类似,foreach
循环中的迭代变量也不是集合元素本身,系统只是把值赋给变量,同样集合也不能改变。
使用Lambda
表达式遍历Iterator
Java8为Iterator
新增forEachRemaining()
方法,该方法所需参数同样也是函数式接口,原理类似,调用时将集合元素传给Consumer
的accept(T t)方法。
Collection names = new HashSet();
names.add("张三");
names.add("李四");
Iterator it = names.iterator();
it.forEachRemaining(obj -> System.out.println(" "+obj));
本质上还是遍历集合names
,所有上面的方法也可以归为遍历集合方法的一种,利用Iterator
的forEachRemaining
方法和Lambda
表达式遍历,又比Iterator
自己提供的方法遍历简洁了一点。
最近优化了站点留言,欢迎访问主站点!