Java 集合框架 Collection的介绍和常用方法,iterator迭代器遍历集合的方法和原理

这个我没学过,每次遇到都有点懵,今天补补课,好记性不如烂博客~
在这里插入图片描述
因为数组存储引用数据类型时有局限性,比如不能自动增长,为了方便封装了一些集合类供使用。

数组与集合的区别

数组可以存储基本数据类型也可以存储引用类型,集合只可以存引用数据类型(对象),但是利用JDK1.5自动装箱的特性,基本数据类型会被自动转换成对象,所以不影响。
数组长度是不可变的,集合的长度是可变的,可以随着元素的增加而增长(有的还是通过数组实现的,重新new一个1.5倍的数组,然后把原来数组中的数据存进去,原来的数组变成垃圾,1.5倍增长是一个折中的办法为了避免频繁地产生垃圾)。

集合继承体系图

在这里插入图片描述
这些集合名字左边表示通过算法什么实现,右边表示派别(除了Vector),Vector是最早有的集合JDK1.0就有了,和ArrayList很像,Vector是线程安全的,ArrayList是线程不安全的。
ArrayList是通过数组实现,LinekedList是通过链表实现。
Collection就是所有集合的根接口。

Collection的常用方法:add、clear、contains、equals、isEmpty、addAll

常规操作: 父类引用指向子类对象,通过add添加元素,clear清空。
clear()方法中从此集合中删除所有元素,只是把引用的指向删除了,集合中不再指向那些对象了,那些对象在堆中会变成垃圾,随后被垃圾回收机制回收。

 	Collection coll = new ArrayList();
    coll.add("a");
    coll.add("b");
    System.out.println(coll);
    coll.clear(); 
    System.out.println(coll);

运行结果:
[a, b]
[]

contains方法判断是否包含指定元素,equals方法不是集合与元素之间的比较,而是集合与集合之间的比较。(List是有序的,相同元素顺序不同是不相等的)
isEmpty()方法判断集合是否为空。

Collection col1 = new ArrayList();
col1.add("a");
col1.add("b");
System.out.println(col1.contains("a"));//是否包含该元素

Collection col2 = new ArrayList();
col2.add("b");
col2.add("a");
System.out.println(col2.equals(col1));//是否相等

运行结果:
true
false

remove方法用于移除指定元素,并且返回boolean表示移除成功与否。
size方法获取集合中元素个数

Collection col1 = new ArrayList();
col1.add("a");
col1.add("b");
col1.remove("a");
System.out.println(col1);
System.out.println(col1.remove("c"));//是否移除元素成功

运行结果:
[b]
false

Collection的高级方法:addAll、containsAll、removeAll、retainAll

Collection col1 = new ArrayList();
col1.add("a");
col1.add("b");
Collection col2 = new ArrayList();
col2.add("c");
col2.add("d");

col1.add(col2);
System.out.println(col1);
System.out.println(col1.size());

运行结果:
[a, b, [c, d]]
3
add方法在添加的是另一个集合的时候会把整个集合当做一个元素填入。
如果想要把另一个集合所有元素加到这个集合中,需要用的是addAll方法:

Collection col1 = new ArrayList();
col1.add("a");
col1.add("b");
Collection col2 = new ArrayList();
col2.add("c");
col2.add("d");
col1.addAll(col2);
System.out.println(col1);
System.out.println(col1.size());

运行结果:
[a, b, c, d]
4

扫描二维码关注公众号,回复: 11513562 查看本文章

containsAll方法用于比较调用的集合是否包含传入的集合:

Collection col1 = new ArrayList();
col1.add("a");
col1.add("b");
Collection col2 = new ArrayList();
col2.add("c");
col2.add("b");

System.out.println(col1.containsAll(col2));

运行结果:false

removeAll删除的是两个集合的交集,一个元素都没有被删除,返回false。

col1.add("a");
col1.add("b");
Collection col2 = new ArrayList();
col2.add("c");
col2.add("b");

System.out.println(col1.removeAll(col2));
System.out.println(col1);

运行结果:
true
[a]

retainAll用来取两个集合的交集。当调用的集合元素没有被改变,返回false。

Collection col1 = new ArrayList();
col1.add("a");
col1.add("b");
Collection col2 = new ArrayList();
col2.add("c");
col2.add("d");

System.out.println(col1.retainAll(col2));
System.out.println(col1);

运行结果:true
[]

iterator迭代器遍历集合的方法

如果要遍历集合,可以转为数组再遍历,但是这样有点麻烦。可以封装好的函数iterator获取iterator迭代器来遍历集合。

Collection col1 = new ArrayList();
col1.add("a");
col1.add("b");
col1.add("c");
col1.add("d");

Iterator it =  col1.iterator();//获取iterator迭代器
while (it.hasNext()){
    Object obj1 = it.next();//使用it.next()元素就会往后移一位,一次循环应该只用一次
    System.out.println(obj1);
}

运行结果:
a
b
c
d
或者使用for循环(可以节省点内存,循环结束以后迭代器就会被释放):

for (Iterator i = col1.iterator();i.hasNext();){
    Object obj1 = i.next();
    System.out.println(obj1);
}

void forEachRemaining(Consumer action),这是Java 8为Iterator新增的默认方法,该方法可使用Lambda表达式来遍历集合元素。

List l = new ArrayList();
l.add(1);
l.add(2);
ListIterator lI = l.listIterator();
lI.forEachRemaining(str->{
    System.out.println(str);
});

Iterator迭代器的原理

为什么iterator要设置成接口,不直接在iterator类实现呢?因为collection底下的子类(例如ArrayList类、LinkedList类)他们的数据存储结构和迭代方式是不一样的,所以要设置成接口让他们用内部类各自实现。
那为什么不直接在这些子类里面直接定义hasNext()、next()这些方法呢,因为这样做的话整个体系中的类都要定义这些方法,过于臃肿,而且用接口能保证整个集合体系的遍历方式都是next和hasNext。

Iterator接口里面有四个抽象方法(JDK1.8版本):
在这里插入图片描述
要调用这些方法肯定有子类对他们进行重写,事实上就是子类中的内部类重写了这些方法,比如说在上一小节的例子中,就是ArrayList类中的内部类Itr继承了Iterator接口,重写了这些方法。
在这里插入图片描述
调用iterator()获取迭代器时,表面上(编译时)调用的是collection中的方法,实际上(运行中)调用的是collection的子类ArrayList类中的方法(因为创建对象时父类引用了子类对象,Collection col1 = new ArrayList();),在ArrayList类中,iterator()方法会创建 继承自Iterator的内部类Itr的一个对象,并且返回这个对象。

后续调用的hasNext()、next()等方法,运行时都是调用的ArrayList内部类Itr的方法,编译时调用的是Iterator这个接口中的方法。

猜你喜欢

转载自blog.csdn.net/weixin_43580841/article/details/107446358