1.集合的由来:
我们学习的是面向对象的语言。而面向对象语言对事物的描述是通过对象体现的。为了方便对多个对象进行操作,我们就必须把多个对象进行存储。而要想存储多个对象,就不能是一个基本的变量,而应该是一个容器类型的变量。在我们目前所学过的知识里面,有哪些是容器类型的呢?数组和StringBuffer。但是StringBuffer的结果是一个字符串, 不一定符合我们的要求,所以我们只能选择数组,这就是对象数组。而对象数组又不能适应变化的需求。因为数组的长度是固定的。这个时候,为了适应变化的需求,java就提供了集合框架。
2.集合和数组的区别?
1.长度的区别
数组的长度固定,而集合的长度可变。
2.内容不同
数组存储的是同一种类型的元素,而集合可以存储不同类型的元素。
3.元素的数据类型
数组可以存储基本数据类型,也可以存储引用数据类型。
集合只能存储引用数据类型。
3.集合继承体系的由来
集合是存储多个元素的,但是,存储多个元素我们也是有不同需求的;比如说,我要这多个元素中不能有相同的元素。再比如说,我要这多个元素按照某种规则排序。针对不同的需求,java就提供了不同的集合类。这样呢,java就提供了很多个集合类,这多个集合类的数据结构不同。结构不同不重要,重要的是能存储数据,并且保证还能够使用这些东西,比如判断,获取等等。既然这样,这多个集合类是有共性的内容,我们把这些集合类的共性内容不断进行抽象,最终就能形成集合的继承体系结构。
4.数据结构解释
数据的物理结构不同,即数据的存储结构不同。
5.集合继承体系的图解
6.Collection接口概述
Collection层次结构中的根接口。Collection中存储的对象,称为Collection中的元素。一些Collection允许有重复的元素,而另一些则不允许有重复的元素。一些Collection是有序的,而另外一些则是无序的。
7.Collection的功能概述
添加功能:
public boolean add(E e):添加一个元素
public boolean addAll(Collection c):存储一个集合的元素
删除功能:
public void clear():移除所有元素
public boolean remove(E e):移除一个元素
public boolean removeAll(Collection c):移除一个集合的元素
判断功能:
public boolean contains(E e):判断集合中是否存在指定的元素
public boolean containsAll(Collection c):判断集合是否包含指定的集合元素
public boolean isEmpty():判断集合是否为空
获取功能:
public Iterator<E> iterator():返回在此集合的元素上的迭代的迭代器
交集功能:
public boolean retainAll(Collection c):两个集合都有的元素
长度功能
public int size():返回集合中元素的个数
把集合转换为数组
public Object[] toArray()
package com; import java.util.ArrayList; import java.util.Collection; /** * 集合框架 * * 集合的由来: * 我们学习的是面向对象的语言。而面向对象语言对事物的描述是通过对象体现的。为了方便对多个对象进行操作, * 我们就必须把多个对象进行存储。而要想存储多个对象,就不能是一个基本的变量,而应该是一个容器类型的变量。 * 在我们目前所学过的知识里面,有哪些是容器类型的呢?数组和StringBuffer。 * 但是StringBuffer的结果是一个字符串, 不一定符合我们的要求,所以我们只能选择数组,这就是对象数组。 * 而对象数组又不能适应变化的需求。因为数组的长度是固定的。这个时候,为了适应变化的需求,java就提供了集合框架。 * * 集合和数组的区别? * 1.长度的区别 * 数组的长度固定,而集合的长度可变。 * 2.内容不同 * 数组存储的是同一种类型的元素,而集合可以存储不同类型的元素。 * 3.元素的数据类型 * 数组可以存储基本数据类型,也可以存储引用数据类型 * 集合只能存储引用数据类型 * * 集合是存储多个元素的,但是,存储多个元素我们也是有不同需求的;比如说,我要这多个元素中不能有相同的元素。 * 再比如说,我要这多个元素按照某种规则排序。针对不同的需求,java就提供了不同的集合类。 * 这样呢,java就提供了很多个集合类,这多个集合类的数据结构不同。结构不同不重要,重要的是能存储数据, * 并且保证还能够使用这些东西,比如判断,获取等等。既然这样,这多个集合类是有共性的内容,我们把这些集合类的 * 共性内容不断进行抽象,最终就能形成集合的继承体系结构。 * * 数据结构:数据的物理结构不同,即数据的存储结构不同。 * * Collection的功能概述 * 添加功能: * public boolean add(E e):添加一个元素 * public boolean addAll(Collection c):存储一个集合的元素 * 删除功能: * public void clear():移除所有元素 * public boolean remove(E e):移除一个元素 * public boolean removeAll(Collection c):移除一个集合的元素 * 判断功能: * public boolean contains(E e):判断集合中是否存在指定的元素 * public boolean containsAll(Collection c):判断集合是否包含指定的集合元素 * public boolean isEmpty():判断集合是否为空 * 获取功能: * public Iterator<E> iterator():返回在此集合的元素上的迭代的迭代器 * 交集功能 * public boolean retainAll(Collection c):两个集合都有的元素 * 长度功能 * public int size():返回集合中元素的个数 * 把集合转换为数组 * public Object[] toArray() * * * * * */ public class CollectionDemo { public static void main(String[] args) { //创建集合对象 Collection c = new ArrayList(); System.out.println(c);//[] //public boolean add(E e):添加一个元素 System.out.println(c.add("hello"));//true System.out.println(c);//[hello] c.add("world"); c.add("java"); System.out.println(c);//[hello, world, java] //public boolean contains(E e):判断集合中是否存在指定的元素 System.out.println(c.contains("hello"));//true //public boolean isEmpty():判断集合是否为空 System.out.println(c.isEmpty());//false //public int size():返回集合中元素的个数 System.out.println(c.size());//3 //public boolean remove(E e):移除一个元素 c.remove("hello"); System.out.println(c);//[world, java] //public void clear():移除所有元素 c.clear(); System.out.println(c);//[] } }
package com; import java.util.ArrayList; import java.util.Collection; public class CollectionDemo2 { public static void main(String[] args) { //创建集合1 Collection c1 = new ArrayList(); c1.add("abc1"); c1.add("abc2"); c1.add("abc3"); c1.add("abc4"); //创建集合2 Collection c2 = new ArrayList(); c2.add("abc4"); c2.add("abc5"); c2.add("abc6"); c2.add("abc7"); System.out.println("c1:"+c1+",c2:"+c2);//c1:[abc1, abc2, abc3, abc4],c2:[abc4, abc5, abc6, abc7] //public boolean addAll(Collection c) c1.addAll(c2); System.out.println("c1:"+c1+",c2:"+c2);//c1:[abc1, abc2, abc3, abc4, abc4, abc5, abc6, abc7],c2:[abc4, abc5, abc6, abc7] //public boolean removeAll(Collection c) 只要有一个被移除了,就算移除 c1.removeAll(c2); System.out.println("c1:"+c1+",c2:"+c2);//c1:[abc1, abc2, abc3],c2:[abc4, abc5, abc6, abc7] //public boolean containsAll(Collection c) //只有包含所有的元素,才叫包含 System.out.println("containsAll:"+c1.containsAll(c2));//containsAll:false //public boolean retainAll(Collection c)求交集 //假设有两个集合A,B //A对B的交集,最终的结果保存在A中,B不变 //返回值表示的是A是否发生变化 System.out.println("retainAll:"+c1.retainAll(c2));//retainAll:true System.out.println("c1:"+c1);//c1:[] System.out.println("c2:"+c2);//c2:[abc4, abc5, abc6, abc7] } }
8.集合的遍历
package com; import java.util.ArrayList; import java.util.Collection; /** * 集合的遍历,其实就是一次获取集合章的每一个元素 * public Object[] toArray() 把集合转成数组,可以实现集合的遍历 * */ public class CollectionDemo3 { public static void main(String[] args) { //创建集合对象 Collection<String> c = new ArrayList<String>(); //添加元素 c.add("hello"); c.add("world"); c.add("java"); //遍历 //public Object[] toArray() Object[] array = c.toArray(); for (int i = 0; i < array.length; i++) { String str = (String)array[i]; System.out.print(str+" ");//hello world java } } }
package com; /** * 学生类 * */ public class Student { private String name; private int age; public Student(){} public Student(String name,int age){ this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } } package com; import java.util.ArrayList; import java.util.Collection; /** * 练习:用集合存储5个学生对象,并把学生对象进行遍历 * * 分析: * 1.创建学生类 * 2.创建集合对象 * 3.创建学生对象 * 4.把学生添加到集合 * 5.把集合转化成数组 * 6.遍历数组 * */ public class StudentDemo { public static void main(String[] args) { //创建集合对象 Collection<Student> c = new ArrayList<Student>(); //创建学生对象 Student s1 = new Student("周星驰",35); Student s2 = new Student("风清扬",22); Student s3 = new Student("宋江",58); Student s4 = new Student("武松",63); Student s5 = new Student("马蓉",130); //把学生对象添加到集合中 c.add(s1); c.add(s2); c.add(s3); c.add(s4); c.add(s5); //把集合转换成数组 Object[] obj = c.toArray(); //遍历数组,输出学生信息 for (int i = 0; i < obj.length; i++) { System.out.println(obj[i]); } } } Student [name=周星驰, age=35] Student [name=风清扬, age=22] Student [name=宋江, age=58] Student [name=武松, age=63] Student [name=马蓉, age=130]
9.集合之迭代器
package com; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * public Iterator<E> iterator() 迭代器,专门用于遍历集合的方式 * */ public class CollectionDemo1 { public static void main(String[] args) { //创建集合对象 Collection<String> c = new ArrayList<String>(); //添加元素 c.add("hello"); c.add("world"); c.add("java"); //使用迭代器进行迭代 for (Iterator<String> iteraotr = c.iterator(); iteraotr.hasNext(); ) { String value = iteraotr.next(); System.out.println(value); } } } hello world java
package com; /** * 学生类 * */ public class Student { private String name; private int age; public Student(){} public Student(String name,int age){ this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } } package com; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * 练习:用集合存储5个学生对象,并把学生对象进行遍历,用迭代进行比那里 * */ public class CollectionDemo4 { public static void main(String[] args) { //创建集合对象 Collection<Student> c = new ArrayList<Student>(); //创建学生对象 Student s1 = new Student("周星驰",35); Student s2 = new Student("风清扬",22); Student s3 = new Student("宋江",58); Student s4 = new Student("武松",63); Student s5 = new Student("马蓉",130); //把学生对象存储到集合之中 c.add(s1); c.add(s2); c.add(s3); c.add(s4); c.add(s5); //使用迭代器进行迭代 for (Iterator<Student> iterator = c.iterator();iterator.hasNext(); ) { Student stu = iterator.next(); System.out.println(stu); } } } Student [name=周星驰, age=35] Student [name=风清扬, age=22] Student [name=宋江, age=58] Student [name=武松, age=63] Student [name=马蓉, age=130]
10.迭代器原理
迭代器,是遍历集合的一种方式。
迭代器是依赖于集合而存在的。
集合的使用步骤
1.创建集合对象
2.创建元素对象
3.把元素添加到集合
4.遍历集合
4.1通过集合对象获取迭代器对象
4.2通过迭代器对象的hasNext()方法判断是否有元素
4.3通过迭代器对象的next()方法获取元素并移动到下一个位置
为什么迭代器不定义成一个类,而定义成一个接口?
假设迭代器定义的是一个类,这样我们就可以创建该类的对象,调用该类的方法来实现集合的遍历。但是,我们知道,java提供了很多的集合类,而这些集合类的数据结构是不同的,所以,存储的方式和遍历的方式应该是不同的。进而它们的遍历方式也不一样的,最终,就没有迭代器类。
而无论你是哪种集合,你都应该具备获取元素的操作,并且,最好有辅助于判断功能。这样,在获取前,先判断。这样就更不容易出错。也就是说,判断和获取功能应该是一个集合遍历所具备,而每个集合的方式又不太一样,所以我们把判断和获取的功能提取出来,兵不提取具体实现,这种方式就是接口。
那么,真正的具体的实现类在哪里?在真正的具体的子类中。以内部类的方式体现的。
那么我们可以从源代码中来看是否和上面分析的一样呢?欲知后事如何,且看下面分解。
package java.util; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.stream.StreamSupport; public interface Collection<E> extends Iterable<E> { int size(); boolean isEmpty(); boolean contains(Object o); Iterator<E> iterator();//获取迭代器接口 Object[] toArray(); <T> T[] toArray(T[] a); boolean add(E e); boolean remove(Object o); boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean removeAll(Collection<?> c); default boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); boolean removed = false; final Iterator<E> each = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; } boolean retainAll(Collection<?> c); void clear(); boolean equals(Object o); int hashCode(); @Override default Spliterator<E> spliterator() { return Spliterators.spliterator(this, 0); } default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } default Stream<E> parallelStream() { return StreamSupport.stream(spliterator(), true); } }
从上面我们知道Collection接口继承了Iterable接口,并且在Collection接口中有获取迭代器接口的方法。
Iterator<E> iterator();//获取迭代器接口
因为Collection接口继承了Iterable接口,所以可以推测在Iterable接口中也有一个获取迭代器接口的方法。因为接口是不能有实现方法的。
那么下面我们去看Iterable接口的源码。
package java.lang; import java.util.Iterator; import java.util.Objects; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; public interface Iterable<T> { Iterator<T> iterator();//获取迭代器的接口的方法 default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } default Spliterator<T> spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); } }
我们可以看到,在Iterable接口中有获取迭代器接口的方法。
而Iterable接口是没有父接口的,那么现在我们去看一下Iterator接口吧,看看它有什么方法
package java.util; import java.util.function.Consumer; public interface Iterator<E> { boolean hasNext();//判断是否包含下一个元素 E next();//获取下一个元素的值 default void remove() { throw new UnsupportedOperationException("remove"); } default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) action.accept(next()); } }
我们可以看出在Iterator接口中有我们经常用的方法,
boolean hasNext();//判断是否包含下一个元素 E next();//获取下一个元素的值
那么现在我们去看一下Collection的子接口List接口
/* * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. package java.util; public interface List<E> extends Collection<E> { int size(); boolean isEmpty(); boolean contains(Object o); Iterator<E> iterator();//获取迭代器接口 Object[] toArray(); <T> T[] toArray(T[] a); boolean add(E e); boolean remove(Object o); boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean addAll(int index, Collection<? extends E> c); boolean removeAll(Collection<?> c); boolean retainAll(Collection<?> c); void clear(); boolean equals(Object o); int hashCode(); E get(int index); E set(int index, E element); void add(int index, E element); E remove(int index); int indexOf(Object o); int lastIndexOf(Object o); ListIterator<E> listIterator(); ListIterator<E> listIterator(int index); List<E> subList(int fromIndex, int toIndex); }
那么我们可以看出在List接口中也有一个获取迭代器接口的方法,why?当然因为List接口继承了Collection啦,而Collection接口中就有一个获取迭代器接口的方法。
Iterator<E> iterator();//获取迭代器接口
到现在距离我们推测的应该很接近了,下面我们看看List接口的实现类ArrayList吧。看一下是否和我们推测的差不多。
package java.util; public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8683452581122892189L; private static final int DEFAULT_CAPACITY = 10; private static final Object[] EMPTY_ELEMENTDATA = {}; private transient Object[] elementData; private int size; public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; } public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } public void trimToSize() { modCount++; if (size < elementData.length) { elementData = Arrays.copyOf(elementData, size); } } public void ensureCapacity(int minCapacity) { int minExpand = (elementData != EMPTY_ELEMENTDATA) // any size if real element table ? 0 // larger than default for empty table. It's already supposed to be // at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } private void ensureCapacityInternal(int minCapacity) { if (elementData == EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } public int size() { return size; } public boolean isEmpty() { return size == 0; } 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; } public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; } public Object clone() { try { @SuppressWarnings("unchecked") ArrayList<E> v = (ArrayList<E>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } } public Object[] toArray() { return Arrays.copyOf(elementData, size); } @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } @SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; } public E get(int index) { rangeCheck(index); return elementData(index); } public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; return oldValue; } 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 } public void clear() { modCount++; for (int i = 0; i < size; i++) elementData[i] = null; size = 0; } public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; } protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); int newSize = size - (toIndex-fromIndex); for (int i = newSize; i < size; i++) { elementData[i] = null; } size = newSize; } private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size; } public boolean removeAll(Collection<?> c) { return batchRemove(c, false); } public boolean retainAll(Collection<?> c) { return batchRemove(c, true); } private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // clear to let GC do its work for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; } private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ int expectedModCount = modCount; s.defaultWriteObject(); s.writeInt(size); for (int i=0; i<size; i++) { s.writeObject(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { elementData = EMPTY_ELEMENTDATA; // Read in size, and any hidden stuff s.defaultReadObject(); // Read in capacity s.readInt(); // ignored if (size > 0) { // be like clone(), allocate array based upon size not capacity ensureCapacityInternal(size); Object[] a = elementData; // Read in all elements in the proper order. for (int i=0; i<size; i++) { a[i] = s.readObject(); } } } public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); } public ListIterator<E> listIterator() { return new ListItr(0); } public Iterator<E> iterator() {//1.这边就是实现父接口的抽象方法 return new Itr();//2.这边是new的Iterator的子类,那么这个Itr是什么鬼,内部类啊 } //3.看这里,是不是,内部类实现了Iterator接口,那么就是意味着每个子类, //比如ArrayList,LinkedList应该都有类似的实现啦,太厉害了,jdk的作者大神,膜拜吧 private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } private class ListItr extends Itr implements ListIterator<E> { ListItr(int index) { super(); cursor = index; } public boolean hasPrevious() { return cursor != 0; } public int nextIndex() { return cursor; } public int previousIndex() { return cursor - 1; } @SuppressWarnings("unchecked") public E previous() { checkForComodification(); int i = cursor - 1; if (i < 0) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i; return (E) elementData[lastRet = i]; } public void set(E e) { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(lastRet, e); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void add(E e) { checkForComodification(); try { int i = cursor; ArrayList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } } public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); } static void subListRangeCheck(int fromIndex, int toIndex, int size) { if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); if (toIndex > size) throw new IndexOutOfBoundsException("toIndex = " + toIndex); if (fromIndex > toIndex) throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); } private class SubList extends AbstractList<E> implements RandomAccess { private final AbstractList<E> parent; private final int parentOffset; private final int offset; int size; SubList(AbstractList<E> parent, int offset, int fromIndex, int toIndex) { this.parent = parent; this.parentOffset = fromIndex; this.offset = offset + fromIndex; this.size = toIndex - fromIndex; this.modCount = ArrayList.this.modCount; } public E set(int index, E e) { rangeCheck(index); checkForComodification(); E oldValue = ArrayList.this.elementData(offset + index); ArrayList.this.elementData[offset + index] = e; return oldValue; } public E get(int index) { rangeCheck(index); checkForComodification(); return ArrayList.this.elementData(offset + index); } public int size() { checkForComodification(); return this.size; } public void add(int index, E e) { rangeCheckForAdd(index); checkForComodification(); parent.add(parentOffset + index, e); this.modCount = parent.modCount; this.size++; } public E remove(int index) { rangeCheck(index); checkForComodification(); E result = parent.remove(parentOffset + index); this.modCount = parent.modCount; this.size--; return result; } protected void removeRange(int fromIndex, int toIndex) { checkForComodification(); parent.removeRange(parentOffset + fromIndex, parentOffset + toIndex); this.modCount = parent.modCount; this.size -= toIndex - fromIndex; } public boolean addAll(Collection<? extends E> c) { return addAll(this.size, c); } public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); int cSize = c.size(); if (cSize==0) return false; checkForComodification(); parent.addAll(parentOffset + index, c); this.modCount = parent.modCount; this.size += cSize; return true; } public Iterator<E> iterator() { return listIterator(); } public ListIterator<E> listIterator(final int index) { checkForComodification(); rangeCheckForAdd(index); final int offset = this.offset; return new ListIterator<E>() { int cursor = index; int lastRet = -1; int expectedModCount = ArrayList.this.modCount; public boolean hasNext() { return cursor != SubList.this.size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= SubList.this.size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (offset + i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[offset + (lastRet = i)]; } public boolean hasPrevious() { return cursor != 0; } @SuppressWarnings("unchecked") public E previous() { checkForComodification(); int i = cursor - 1; if (i < 0) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (offset + i >= elementData.length) throw new ConcurrentModificationException(); cursor = i; return (E) elementData[offset + (lastRet = i)]; } public int nextIndex() { return cursor; } public int previousIndex() { return cursor - 1; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { SubList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = ArrayList.this.modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void set(E e) { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(offset + lastRet, e); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void add(E e) { checkForComodification(); try { int i = cursor; SubList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = ArrayList.this.modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (expectedModCount != ArrayList.this.modCount) throw new ConcurrentModificationException(); } }; } public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, offset, fromIndex, toIndex); } private void rangeCheck(int index) { if (index < 0 || index >= this.size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private void rangeCheckForAdd(int index) { if (index < 0 || index > this.size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+this.size; } private void checkForComodification() { if (ArrayList.this.modCount != this.modCount) throw new ConcurrentModificationException(); } } }
我们可以看到这样的代码
public Iterator<E> iterator() {//1.这边就是实现父接口的抽象方法 return new Itr();//2.这边是new的Iterator的子类,那么这个Itr是什么鬼,内部类啊 } //3.看这里,是不是,内部类实现了Iterator接口,那么就是意味着每个子类, //比如ArrayList,LinkedList应该都有类似的实现啦,太厉害了,jdk的作者大神,膜拜吧 private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
那么到了这里,就和我们推测的一样了。
那么图解如下所示
11.练习
11.1存储字符串并遍历
package com; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * 需求:存储字符串并遍历 * 分析: * 1.创建集合对象 * 2.创建字符串对象 * 3.把字符串对象添加到集合中 * 4.遍历集合 */ public class CollectionTest { public static void main(String[] args) { //创建集合对象 Collection<String> c = new ArrayList<String>(); //创建字符串对象 String s1 = "hello"; String s2 = "world"; String s3 = "java"; //把字符串对象添加到集合中 c.add(s1); c.add(s2); c.add(s3); //遍历集合 方式一,将集合转换为数组,再遍历 // String[] strs = (String[]) c.toArray(); // for (int i = 0; i < strs.length; i++) { // System.out.println(strs[i]); // } // 上面的这种方式是错误的,因为Object[]怎么可以转换成String[]数组呢 // 何况在Collection中的toArray()的定义是这样的 /** * Object[] toArray(); */ //所以,只能先将集合转换为Object数组,然后通过for循环将每个元素取出来, //再转换为String Object[] obj = c.toArray(); for (int i = 0; i < obj.length; i++) { String str = (String)obj[i]; System.out.println(str); } //遍历集合方式二:直接通过迭代器的方式输出数组 for (Iterator<String> iterator = c.iterator(); iterator.hasNext(); ) { String str = iterator.next(); System.out.println(str); } } }
11.2存储学生对象并遍历
package com; /** * 学生类 * */ public class Student { private String name; private int age; public Student(){} public Student(String name,int age){ this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } } package com; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * 练习:用集合存储5个学生对象,并把学生对象进行遍历 * * 分析: * 1.创建学生类 * 2.创建集合对象 * 3.创建学生对象 * 4.把学生添加到集合 * 5.把集合转化成数组 * 6.遍历数组 * */ public class StudentDemo { public static void main(String[] args) { //创建集合对象 Collection<Student> c = new ArrayList<Student>(); //创建学生对象 Student s1 = new Student("周星驰",35); Student s2 = new Student("风清扬",22); Student s3 = new Student("宋江",58); Student s4 = new Student("武松",63); Student s5 = new Student("马蓉",130); //把学生对象添加到集合中 c.add(s1); c.add(s2); c.add(s3); c.add(s4); c.add(s5); //把集合转换成数组 Object[] obj = c.toArray(); //遍历集合方式一,输出学生信息 for (int i = 0; i < obj.length; i++) { System.out.println(obj[i]); } //遍历集合方式二:通过迭代器 for (Iterator<Student> iterator = c.iterator(); iterator.hasNext(); ) { Student student = iterator.next(); System.out.println(student); } } }