集合类的继承关系和基本方法
数组和集合
数组的长度是固定,改变数组长度的方式是创建新的数组,将旧数组复制到新的数组里.
集合类能存储任意长度的对象,集合的长度可以随着元素的增加而增加,随元素减少而减少
数组和集合的区别
数组既可以存储基本数据类型(存储值),又可以存储引用数据类型(可以不同种对象,存储地址值),数组长度是固定的,不能自动增长
集合只能存储引用数据类型(可以不同种对象,地址值),如果存储基本数据类型时,会自动装箱变成相应的包装类,集合的长度的是可变的,可以根据元素的增加而自动增长
集合是一个接口,它的继承子类和实现类主要有:(图片只绘制了主要框架,具体继承和实现的类没标出)
集合是接口,没有构造方法,集合的初始化可以采用多态的形式,集合引用指向子类对象
集合接口的主要方法:
boolean add(E e)向集合中添加一个元素,如果E是集合类,就会把集合e当作元素添加到原集合中
boolean addAll(Collection c)向集合中添加一个集合的元素,添加了c中的每个元素
boolean remove(Object o)从集合中移除指定元素,
boolean removeAll(Collection c)从集合中移除所有(即存在于原集合又存在于集合c中的)元素
void clear()清空集合
boolean contains(Object o)集合中是否包含某个元素(比较的是该元素与整个集合的所有元素的地址,如果元素的类没有重写equals方法,则返回不正确的值,所以调用该方法要确保已经重写equals方法)
boolean containsAll(Collection c)集合中是否包含了指定集合的所有元素,
boolean isEmpty() 集合是否不包含元素
int size() 返回集合中元素的个数
Object toArrays()返回一个Object类型数组
Iterator<E> iterator()返回一个迭代器对象,这个后面说.
import java.util.ArrayList;
import java.util.Collection;
public class CollectionTest02 {
public static void main(String[] args) {
Collection c1 = new ArrayList();
Collection c2 = new ArrayList();
c1.add("a");// 向集合中添加元素
c1.add("b");
c1.add("c");
c1.add("d");
c1.add("e");
c1.add("f");
c2.add("a");
c2.add("b");
c2.add("c");
c2.add("d");
c2.add("d");
c2.add("h");
System.out.println(c1);// c1=["a","b","c","d","e","f"]
System.out.println(c2);// c2=["a","b","c","d","h"]
// contain
System.out.println(c1.contains("a"));// true
// containsAll
System.out.println(c1.containsAll(c2));// false
// remove
c1.remove("a");// c1=["b","c","d","e","f"]
// remove集合中不存在的元素值时,返回false
System.out.println(c1.remove("g"));// false
System.out.println(c1);
// removeAll
c1.removeAll(c2);// c1=[e,f]
System.out.println(c1);
// clear
c2.clear();// c2=[]
System.out.println(c2.isEmpty());// true
System.out.println(c1.size());// 2
// c2重新添加一些元素
c2.add("c");
c2.add("d");
c2.add("d");
c2.add("h");
c1.add(c2);
System.out.println(c1);
c1.addAll(c2);
System.out.println(c1);
}
}
out:
a, b, c, d, e, f]
[a, b, c, d, d, h]
true
false
false
[b, c, d, e, f]
[e, f]
true
2
[e, f, [c, d, d, h]]
[e, f, [c, d, d, h], c, d, d, h]
当添加自己定义的对象时
对于打印对对象,Collection接口的子类AbstractedCollection中重写了toString方法,所以打印集合对象不会打印集合对象的地址,而是每个对象元素,但是如果集合中的元素没有重写toString方法,那么打印出来的对象元素还是每个元素的地址,所以,集合中的元素要重写toString方法,有些类已经重写了,比如String类
equals方法,同样对于集合中的元素,如果该元素(是一个对象)没有重写equals方法,那么在集合中的操作是操作该对象引用的堆内存地址,remove方法删除不了该对象,contains方法返回的值也不正确,所以要重写equals方法
import java.util.ArrayList;
import java.util.Collection;
import students.Student;
public class CollectionTest03 {
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add(new Student(12, "张"));
c1.add(new Student(13, "李"));
c1.add(new Student(14, "赵"));
c1.add(new Student(15, "刘"));
// 如果没有重写equals方法,删除的只是s1的地址,s1的地址不在集合中,所以还是原来的集合
// contains比较的也是地址,那么返回false
// 重写equals方法后,才会比较引用的内容,remove和contains方法才生效
Student s1 = new Student(13, "李");
System.out.println(c1.contains(s1));
c1.remove(s1);
System.out.println(c1);
// toArray方法,返回Object类型数组
Object[] objs = c1.toArray();
for (int i = 0; i < objs.length; i++) {
System.out.println(objs[i]);
}
// 清除c1集合的全部元素
c1.clear();
System.out.println(c1.isEmpty());
}
}
out:
true
[Student [age=12, name=张], Student [age=14, name=赵], Student [age=15, name=刘]]
Student [age=12, name=张]
Student [age=14, name=赵]
Student [age=15, name=刘]
true
注:ArrayList和其父类AbstractList都实现了List<>接口,效果上没什么特别用途,仅仅是为了让人阅读源码时知道子类实现了该核心接口。就像很多人都知道 ArrayList实现了List接口就够了,而不需要知道它继承AbstractList的相关细节。
Iterator<E> iterator() 获取Iterator接口实例
iterator是集合中的一个重写的方法,Collection继承了Iterable,Iterable接口中定义了返回Iterator实例的方法iterator,iterator实例可以遍历集合
jdk11 Iterable中iterator方法的定义:
Iterator<E> iterator();//只提供一个抽象方法,需要子类实现
Collection的子类下面ArrayList中实现的源码为:
public Iterator<E> iterator() {
return new Itr();
}
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();
}
}
}
Iterator和Iterable在集合中的应用
Iterable是Collection的父接口,Iterator是单独的接口,但是Iterable中有一个方法可以返回Iterator接口的实例
然后在Collection的子类中也有实现Iterator接口及其子接口的内部类,调用对应的方法可以返回Iterator对象
总结:所有的Collection子类
会实现Iteratable
接口以实现foreach
功能,Iteratable
接口的实现又依赖于实现了Iterator
的内部类(参照LinkedList
中listIterator()
和descendingIterator()
的JDK源码)。有的容器类会有多个实现Iterator接口的内部类,通过返回不同的迭代器实现不同的迭代方式。
大致的Iterator,Iterable和Collection关系如下图,但是Collection子类中有多个都定义了实现Iterator接口及其子接口的内部类,
Iterator接口的方法
boolean hasNext() 定义一个指针,返回当前指针指向的索引处是否还有元素,如果有就返回true,此方法不会移动指针
E next()该方法返回当前指针下的元素,同时将指针后移,当该指针移动到最后面时,再调用hasNext返回的就是false,再调用next方法会报出异常java.util.NoSuchElementException
利用iterator方法获取Iterator实例来遍历Collection例子
import java.util.ArrayList;
import java.util.Iterator;
import students.Student;
public class IteratorTest {
public static void main(String[] args) {
ArrayList c1 = new ArrayList();
c1.add(new Student(12, "张"));
c1.add(new Student(13, "李"));
c1.add(new Student(14, "赵"));
c1.add(new Student(15, "刘"));
//for循环遍历集合对象,打印对象
for (Iterator iterator = c1.iterator(); iterator.hasNext();) {
System.out.println(iterator.next());
}
Iterator it = c1.iterator();
// while循环直接打印对象
while (it.hasNext()) {
System.out.println(it.next());
}
// while循环获取元素后,向下转型,调用元素的get方法获取对象属性
while (it.hasNext()) {
Student s = (Student) it.next();
System.out.println(s.getName() + " " + s.getAge());
}
}
}
out:
Student [age=12, name=张]
Student [age=13, name=李]
Student [age=14, name=赵]
Student [age=15, name=刘]
Student [age=12, name=张]
Student [age=13, name=李]
Student [age=14, name=赵]
Student [age=15, name=刘]
参考:https://www.aliyun.com/jiaocheng/773540.html
http://www.monkey1024.com/javase/528
https://www.jianshu.com/p/cf82ab7e51ef
Chinese (Simplified)English | Chinese (Simplified)English |
Text-to-speech function is limited to 200 characters
Options : History : Feedback : Donate | Close |