集合框架与迭代器如何实现高效数据访问?

2026-05-22 10:452阅读0评论SEO资源
  • 内容介绍
  • 相关推荐

本文共计2301个文字,预计阅读时间需要10分钟。

集合框架与迭代器如何实现高效数据访问?

集合框架+集合是数组的升级,数组也是一种集合。集合是一种容器,用于存放对象。不同集合的区别在于,集合可以存放不同类型的对象,且数量不限。如果集合中存放基本数据类型,会自动装箱。

集合框架

集合是数组的升级,数组也是一种集合,集合是一种容器,用于存放对象的容器。不同数组的是,集合可以存放不同的类型,也不限数量。如果在集合中存放基本数据会自动装箱转换成对应的引用类型。

集合存放的是对象的引用(内存地址),对象本身还是在堆中。集合也是一个引用

集合结构

java.util.*该包下存放所有的集合和集合的接口

集合又分三类,有序集合List,无序集合Set,另类是Map接口系列的集合。其中,List和Set都是Collection的子接口。而Collection又是Iterator的子接口,Iterator是迭代器,用于遍历集合中元素的接口;Map系列的集合是以键-值对存储的,Collection系列的集合是单个存储的。

不同的集合,底层对应的数据结构不同,数据结构分:数组、二叉树、链表等。数据结构不同,存储分式不同。

Collection结构图

Map结构图

以上,图中展示的是常用的类,当然还有其他的集合,其中的方法也差不多大同小异,可以自行查阅jdk文档

Q:无序不可重复,无序指的是存储和读取时的顺序,而不是排列顺序。不可重复是指存储的元素不可以重复,比如列表里已经有了1,那么再存进去1,元素个数也不会增加

Iterable接口

是Collection集合的顶层接口,Iterable是迭代接口,用于获取迭代器。

主要方法:

Iterator<T> iterator()

返回一个 T 类型的迭代器

Iterator迭代器

用于遍历集合中的元素。E代表泛型,用于表示未确认的数据类型。

方法

boolean hasNext()

判断容器是否还有可供访问的元素,如果具有更多元素,则返回true

用于判断集合是否还有下一个元素

E next()

让迭代器向前进一位 ,并返回前进反指向的元素。

返回指向的当前元素

例:Collection集合的迭代遍历

Collection list = new ArrayList(); list.add(10.12); list.add(true); list.add("String"); list.add(new Object()); //获取迭代器 Iterator iterator = list.iterator(); //判断是否还有下一位元素 while(iterator.hasNext()){ //前进到下一位,并返回当前元素 Object o = iterator.next(); System.out.println(o); } /* 10.12 true String java.lang.Object@1b6d3586 Process finished with exit code 0*/

Q:迭代器最开始并不是指向集合的第一位,当第一次调用next时迭代器才会进入集合指向第一个元素

Collection接口结构

Collection下又细分Set、List两种。

List系列特点:存储的元素是有序的,先存进去的在读取时先出来,集合中的元素都有对应的下标(索引),可以存在重复的元素

Set系列特点:存储的元素无序,集合中的元素没有下标,且存储的元素不可重复

在没有使用泛型前,Collection可以存储任意的Object子类型,使用泛型后,Collection只能存储某个具体的类型。

Q:集合中不能存储基本类型,如果在添加元素时放的是基本类型,会自动装箱;集合中存储的是对象的引用,不是对象本身

常用方法

boolean add(E e);

向集合中添加元素。如果添加成功,则返回true,否则反之

int size();

返回素合中的元素个数

void clear();

清空该集合的元素

boolean contains(Object o);

判断集合中是否包含指定的元素。包含返回true,否则反之

boolean remove(Object o);

删除集合中指定的元素。删除成功返回true,否则反之

boolean isEmpty();

判断集合是否为空。

Object[] toArray();

将该集合转换为一个数组,返回一个Object类型的数组

例:

Collection colls = new ArrayList(); colls.add(100); colls.add("string"); colls.add(10.12); colls.add(new Object()); colls.add(true); System.out.println(colls.isEmpty()); System.out.println(colls.contains(false)); Object[] objects = colls.toArray(); for (Object o : objects) { System.out.println(o); } System.out.println(colls.size()); System.out.println(colls.remove(10.12)); System.out.println(colls.size()); colls.clear(); System.out.println(colls.size()); /* false false 100 string 10.12 java.lang.Object@1b6d3586 true 5 true 4 0 Process finished with exit code 0*/ contains、remove方法

以ArrayList源码为例。

contains

public boolean contains(Object o) { return indexOf(o) >= 0; } public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }

由源码可知,contains方法底层是通过被参数去调用equals方法,从而去比较集合中的各个元素

存储到集合的元素强烈建议重写equals方法,不然在判断集合中是否包含某个对象时比较的是地址值

例:contains比较两个String元素

Collection c = new ArrayList(); String s1 = new String("123"); c.add(s1); String x = new String("123"); System.out.println(c.contains(x)); /* true Process finished with exit code 0*/

c.contains(x) == x.equals(s1),而String的equals是比较内容的,也就是 “123” =?= “123” => true,所以上面返回的是true

如果比较的参数类型继承Object没有重写equals,那么其比较的必须是地址值,两个不同的对象去比较equals那么就返回false。

如果比较的参数类型重写了equals,比较的是内容,就算是两个不同的对象,只要他们的内容相同,那么就返回true

remove

public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }

ArrayList在做删除元素动作时,底层也会做equals校验

如果集合中有多个重复的元素,那么会删除第一个校验成功的元素。

Q:如果存储的元素类型没有重写equals,那么可能无法删除。因为没有重写过equals的类型,其比较的是两个对象的地址值。

例:remove删除ArrayList中的元素

Collection c = new ArrayList(); String s1 = new String("123"); c.add(s1); String s2 = new String("123"); c.add(s2); System.out.println(c.size());// 2 Sting x = new String("123"); c.remove(x); System.out.println(c.size());//1 /* 2 1 Process finished with exit code 0*/

存在重复的元素只会删除第一个与之校验成功的元素。上面删除的是‘s1’

迭代器的remove方法

获取迭代器Iterator时,迭代器会绑定当前状态下的集合。如果集合结构发生了改变,则需要重新获取迭代器,不然会出现:java.util.CocurrentModificationExcetion异常。

Collection list = new ArrayList(); c.add("hello"); c.add("word"); c.add(12153); Iterator iterator = list.iterator(); while(iterator.hasNext()){ Object o = iterator.next(); if (o.equals(10.12)) iterator.remove(o); } /* Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909) at java.util.ArrayList$Itr.next(ArrayList.java:859) at com.collection.IteratorBase.main(IteratorBase.java:7) Process finished with exit code 1*/

在获取了迭代器后禁止再去改变集合结构(add、remove)。因为此时的迭代器无法主动同步集合的操作,java会认为这是线程不安全的

如果想在迭代时删除集合的元素可以使用迭代器的remove方法,它会去同步集合的删除操作。

Collection list = new ArrayList(); c.add("hello"); c.add("word"); c.add(12153); Iterator iterator = list.iterator(); while(iterator.hasNext()){ Object o = iterator.next(); if (o.equals(10.12)) iterator.remove(o); } 集合遍历拓展


1.foreach循环

foreach循环可以与任何实现了Iterable接口的对象一起工作。Collection接口继承了Iterable接口,因此,类库中的任何集合都可以使用foreach做元素遍历

Collection list = new ArrayList(); list.add(10.12); list.add(true); list.add("String"); list.add(new Object()); System.out.println("-------------"); for (Object obj: list) { System.out.println(obj); }

2.forEachRemaining方法

在Java SE 8中,还可以通过调用forEachRemaining方法并提供一个lambda表达式完成对集合遍历

Collection list = new ArrayList(); list.add(10.12); list.add(true); list.add("String"); list.add(new Object()); Iterator iterator = list.iterator(); iterator.forEachRemaining(element -> System.out.println(element));

forEachRemaining方法最好不要与next方法混合使用

集合框架与迭代器如何实现高效数据访问?

本文共计2301个文字,预计阅读时间需要10分钟。

集合框架与迭代器如何实现高效数据访问?

集合框架+集合是数组的升级,数组也是一种集合。集合是一种容器,用于存放对象。不同集合的区别在于,集合可以存放不同类型的对象,且数量不限。如果集合中存放基本数据类型,会自动装箱。

集合框架

集合是数组的升级,数组也是一种集合,集合是一种容器,用于存放对象的容器。不同数组的是,集合可以存放不同的类型,也不限数量。如果在集合中存放基本数据会自动装箱转换成对应的引用类型。

集合存放的是对象的引用(内存地址),对象本身还是在堆中。集合也是一个引用

集合结构

java.util.*该包下存放所有的集合和集合的接口

集合又分三类,有序集合List,无序集合Set,另类是Map接口系列的集合。其中,List和Set都是Collection的子接口。而Collection又是Iterator的子接口,Iterator是迭代器,用于遍历集合中元素的接口;Map系列的集合是以键-值对存储的,Collection系列的集合是单个存储的。

不同的集合,底层对应的数据结构不同,数据结构分:数组、二叉树、链表等。数据结构不同,存储分式不同。

Collection结构图

Map结构图

以上,图中展示的是常用的类,当然还有其他的集合,其中的方法也差不多大同小异,可以自行查阅jdk文档

Q:无序不可重复,无序指的是存储和读取时的顺序,而不是排列顺序。不可重复是指存储的元素不可以重复,比如列表里已经有了1,那么再存进去1,元素个数也不会增加

Iterable接口

是Collection集合的顶层接口,Iterable是迭代接口,用于获取迭代器。

主要方法:

Iterator<T> iterator()

返回一个 T 类型的迭代器

Iterator迭代器

用于遍历集合中的元素。E代表泛型,用于表示未确认的数据类型。

方法

boolean hasNext()

判断容器是否还有可供访问的元素,如果具有更多元素,则返回true

用于判断集合是否还有下一个元素

E next()

让迭代器向前进一位 ,并返回前进反指向的元素。

返回指向的当前元素

例:Collection集合的迭代遍历

Collection list = new ArrayList(); list.add(10.12); list.add(true); list.add("String"); list.add(new Object()); //获取迭代器 Iterator iterator = list.iterator(); //判断是否还有下一位元素 while(iterator.hasNext()){ //前进到下一位,并返回当前元素 Object o = iterator.next(); System.out.println(o); } /* 10.12 true String java.lang.Object@1b6d3586 Process finished with exit code 0*/

Q:迭代器最开始并不是指向集合的第一位,当第一次调用next时迭代器才会进入集合指向第一个元素

Collection接口结构

Collection下又细分Set、List两种。

List系列特点:存储的元素是有序的,先存进去的在读取时先出来,集合中的元素都有对应的下标(索引),可以存在重复的元素

Set系列特点:存储的元素无序,集合中的元素没有下标,且存储的元素不可重复

在没有使用泛型前,Collection可以存储任意的Object子类型,使用泛型后,Collection只能存储某个具体的类型。

Q:集合中不能存储基本类型,如果在添加元素时放的是基本类型,会自动装箱;集合中存储的是对象的引用,不是对象本身

常用方法

boolean add(E e);

向集合中添加元素。如果添加成功,则返回true,否则反之

int size();

返回素合中的元素个数

void clear();

清空该集合的元素

boolean contains(Object o);

判断集合中是否包含指定的元素。包含返回true,否则反之

boolean remove(Object o);

删除集合中指定的元素。删除成功返回true,否则反之

boolean isEmpty();

判断集合是否为空。

Object[] toArray();

将该集合转换为一个数组,返回一个Object类型的数组

例:

Collection colls = new ArrayList(); colls.add(100); colls.add("string"); colls.add(10.12); colls.add(new Object()); colls.add(true); System.out.println(colls.isEmpty()); System.out.println(colls.contains(false)); Object[] objects = colls.toArray(); for (Object o : objects) { System.out.println(o); } System.out.println(colls.size()); System.out.println(colls.remove(10.12)); System.out.println(colls.size()); colls.clear(); System.out.println(colls.size()); /* false false 100 string 10.12 java.lang.Object@1b6d3586 true 5 true 4 0 Process finished with exit code 0*/ contains、remove方法

以ArrayList源码为例。

contains

public boolean contains(Object o) { return indexOf(o) >= 0; } public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }

由源码可知,contains方法底层是通过被参数去调用equals方法,从而去比较集合中的各个元素

存储到集合的元素强烈建议重写equals方法,不然在判断集合中是否包含某个对象时比较的是地址值

例:contains比较两个String元素

Collection c = new ArrayList(); String s1 = new String("123"); c.add(s1); String x = new String("123"); System.out.println(c.contains(x)); /* true Process finished with exit code 0*/

c.contains(x) == x.equals(s1),而String的equals是比较内容的,也就是 “123” =?= “123” => true,所以上面返回的是true

如果比较的参数类型继承Object没有重写equals,那么其比较的必须是地址值,两个不同的对象去比较equals那么就返回false。

如果比较的参数类型重写了equals,比较的是内容,就算是两个不同的对象,只要他们的内容相同,那么就返回true

remove

public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }

ArrayList在做删除元素动作时,底层也会做equals校验

如果集合中有多个重复的元素,那么会删除第一个校验成功的元素。

Q:如果存储的元素类型没有重写equals,那么可能无法删除。因为没有重写过equals的类型,其比较的是两个对象的地址值。

例:remove删除ArrayList中的元素

Collection c = new ArrayList(); String s1 = new String("123"); c.add(s1); String s2 = new String("123"); c.add(s2); System.out.println(c.size());// 2 Sting x = new String("123"); c.remove(x); System.out.println(c.size());//1 /* 2 1 Process finished with exit code 0*/

存在重复的元素只会删除第一个与之校验成功的元素。上面删除的是‘s1’

迭代器的remove方法

获取迭代器Iterator时,迭代器会绑定当前状态下的集合。如果集合结构发生了改变,则需要重新获取迭代器,不然会出现:java.util.CocurrentModificationExcetion异常。

Collection list = new ArrayList(); c.add("hello"); c.add("word"); c.add(12153); Iterator iterator = list.iterator(); while(iterator.hasNext()){ Object o = iterator.next(); if (o.equals(10.12)) iterator.remove(o); } /* Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909) at java.util.ArrayList$Itr.next(ArrayList.java:859) at com.collection.IteratorBase.main(IteratorBase.java:7) Process finished with exit code 1*/

在获取了迭代器后禁止再去改变集合结构(add、remove)。因为此时的迭代器无法主动同步集合的操作,java会认为这是线程不安全的

如果想在迭代时删除集合的元素可以使用迭代器的remove方法,它会去同步集合的删除操作。

Collection list = new ArrayList(); c.add("hello"); c.add("word"); c.add(12153); Iterator iterator = list.iterator(); while(iterator.hasNext()){ Object o = iterator.next(); if (o.equals(10.12)) iterator.remove(o); } 集合遍历拓展


1.foreach循环

foreach循环可以与任何实现了Iterable接口的对象一起工作。Collection接口继承了Iterable接口,因此,类库中的任何集合都可以使用foreach做元素遍历

Collection list = new ArrayList(); list.add(10.12); list.add(true); list.add("String"); list.add(new Object()); System.out.println("-------------"); for (Object obj: list) { System.out.println(obj); }

2.forEachRemaining方法

在Java SE 8中,还可以通过调用forEachRemaining方法并提供一个lambda表达式完成对集合遍历

Collection list = new ArrayList(); list.add(10.12); list.add(true); list.add("String"); list.add(new Object()); Iterator iterator = list.iterator(); iterator.forEachRemaining(element -> System.out.println(element));

forEachRemaining方法最好不要与next方法混合使用

集合框架与迭代器如何实现高效数据访问?