集合(Collection)
1. 集合的由来?
我们学习的是Java -- 面向对象 -- 操作很多对象 -- 存储 -- 容器(数组和StringBuffer) -- 数组
而数组的长度固定,所以不适合做变化的需求,Java就提供了集合供我们使用。
我们学习的是面向对象语言,而面向对象语言对事物的描述是通过对象体现的,为了方便对多个对象进行操作,我们就必须把这多个对象进行存储。
而要想存储多个对象,就不能是一个基本的变量,而应该是一个容器类型的变量,在我们目前所学过的知识里面,有哪些是容器类型的呢?
数组和StringBuffer。但是呢?StringBuffer的结果是一个字符串,不一定满足我们的要求,所以我们只能选择数组,这就是对象数组。
而对象数组又不能适应变化的需求,因为数组的长度是固定的,这个时候,为了适应变化的需求,Java就提供了集合类供我们使用。
2. 集合和数组的区别?
A:长度
数组长度固定
集合长度可变
B: 存储的数据类型
数组存储的数据可以是基本类型,也可以是引用类型,必须是同一种类型的元素。
集合存储的数据只能是引用类型, 可存储不同引用类型的元素。(例如:Student类型,Teacher类型)
C:元素内容
数组只能存储同一种类型的元素。
集合可存储不同引用类型的元素(其实集合一般存储的也是同一种类型),(例如:Student类型,Teacher类型)
3. 集合的继承体系结构?
由于需求不同,Java就提供了不同的集合类。这些集合类的数据结构(数据的存储方式)不同,但是它们都是要提供 存储、判断、获取 等功能。
我们把它们的共性不断的向上提取,最终就形成了集合的继承体系结构图。
API中说到:
Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。
一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。
即:Collection:是集合的顶层接口,它的子体系有重复的,有唯一的,有有序的,有无序的。
JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。
此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。
先重点学习:
Collection
|--List
|--ArrayList
|--Vector
|--LinkedList
|--Set
|--HashSet
|--TreeSet
4. Collection的功能概述
A:添加功能
boolean add(E e):确保此 collection 包含指定的元素(可选操作)。
boolean add(Object obj):添加一个元素。
boolean addAll(Collection<? extends E> c):将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
boolean addAll(Collection c):添加一个集合的元素。
B:删除功能
void clear():移除此 collection 中的所有元素(可选操作)。//移除所有元素
boolean remove(Object o):从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。//移除一个元素(执行一次移除一个)
boolean removeAll(Collection<?> c):移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
boolean removeAll(Collection c):移除一个集合的元素(只要有一个元素被移除了,就返回true。)
C:判断功能
boolean contains(Object o):如果此 collection 包含指定的元素,则返回 true。//判断集合中是否包含指定的元素
boolean containsAll(Collection<?> c):如果此 collection 包含指定 collection 中的所有元素,则返回 true。
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(只有包含所有的元素,才叫包含,才会返回true)
boolean isEmpty():如果此 collection 不包含元素,则返回 true。//判断集合是否为空(指元素为空,不是对象为空)。该方法是通过对象调用的,若对象为空就不能调用方法了。
D:获取功能
Iterator<E> iterator():返回在此 collection 的元素上进行迭代的Iterator(迭代器)。集合的专用遍历方式。(重点)
E next():返回迭代的下一个元素。抛出: NoSuchElementException - 没有元素可以迭代。
Object next():获取元素,并移动到下一个位置。不要多次使用it.next()方法,因为每次使用都是访问一个对象。
boolean hasNext():如果仍有元素可以迭代,则返回 true。
E:长度功能
int size():返回此 collection 中的元素数。
面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?
F:交集功能(了解)
boolean retainAll(Collection<?> c):仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。//取交集,
boolean retainAll(Collection c)
思考元素去哪了,返回的boolean又是什么意思呢?
解:假设有两个集合A,B。A对B做交集,最终的结果保存在A中,B不变。返回值表示的是A是否发生过改变,改变返回true。
G:把集合转数组(了解)
Object[] toArray():返回包含此 collection 中所有元素的数组。//元素是任意对象类型,所以是以对象形式接收
<T> T[] toArray(T[] a):返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。
/**************************************************************************************************************************/
// 测试不带All的方法
public class CollectionDemo {
public static void main(String[] args) {
// 创建集合对象
// Collection c = new Collection(); //错误,因为接口不能实例化
Collection c = new ArrayList();
// boolean add(Object obj):添加一个元素
System.out.println("add:"+c.add("hello"));//看源码可知永远返回true,说明可以存重复的元素。
c.add("hello");
c.add("world");
c.add("java");
// void clear():移除所有元素
// c.clear();
System.out.println("c:" + c);// c:[hello, hello, world, java]
// boolean remove(Object o):移除一个元素
System.out.println("remove:" + c.remove("hello"));// remove:true(一次移除一个)
System.out.println("remove:" + c.remove("javaee"));// remove:false
System.out.println("c:" + c);// c:[hello, world, java]
// boolean contains(Object o):判断集合中是否包含指定的元素
System.out.println("contains:"+c.contains("hello"));// contains:true
System.out.println("contains:"+c.contains("android"));// contains:false
// boolean isEmpty():判断集合是否为空(指元素是否为空)
System.out.println("isEmpty:"+c.isEmpty());// isEmpty:false
//int size():元素的个数
System.out.println("size:"+c.size());// size:3
}
}
/**************************************************************************************************************************/
/*测试带All的方法
boolean addAll(Collection<? extends E> c):将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
boolean addAll(Collection c):添加一个集合的元素。
boolean removeAll(Collection<?> c):移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
boolean removeAll(Collection c):移除一个集合的元素(只要有一个元素被移除了,就返回true。)
boolean containsAll(Collection<?> c):如果此 collection 包含指定 collection 中的所有元素,则返回 true。
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(只有包含所有的元素,才叫包含,才会返回true)
boolean retainAll(Collection<?> c):仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
boolean retainAll(Collection c):两个集合都有的元素?思考元素去哪了,返回的boolean又是什么意思呢?
*/
public class CollectionDemo {
public static void main(String[] args) {
// 创建集合1
Collection c1 = new ArrayList();
c1.add("abc1");
c1.add("abc2");
c1.add("abc3");
c1.add("abc4");
System.out.println("c1:" + c1);// c1:[abc1, abc2, abc3, abc4]
// 创建集合2
Collection c2 = new ArrayList();
// c2.add("abc1");
// c2.add("abc2");
// c2.add("abc3");
c2.add("abc4");
c2.add("abc5");
c2.add("abc6");
c2.add("abc7");
System.out.println("c2:" + c2);// c2:c2:[abc4, abc5, abc6, abc7]
// boolean addAll(Collection c):添加一个集合的元素
System.out.println("addAll:" + c1.addAll(c2));// addAll:true
System.out.println("c1:" + c1);// c1:[abc1, abc2, abc3, abc4, abc4, abc5, abc6, abc7]
//boolean removeAll(Collection c):移除一个集合的元素(只要有一个元素被移除了,就返回true。)
System.out.println("removeAll:"+c1.removeAll(c2));// removeAll:true
System.out.println("c1:" + c1);// c1:[abc1, abc2, abc3]
//boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(只有包含所有的元素,才叫包含,才会返回true)
c1.add("abc4");
System.out.println("c1:" + c1);// c1:[abc1, abc2, abc3, abc4]
System.out.println("c2:" + c2);// c2:[abc4, abc5, abc6, abc7]
System.out.println("containsAll:"+c1.containsAll(c2));// containsAll:false
//boolean retainAll(Collection c):返回的boolean又是什么意思呢?
//假设有两个集合A,B。A对B做交集,最终的结果保存在A中,B不变。返回值表示的是A是否发生过改变。
System.out.println("c1:" + c1);// c1:[abc1, abc2, abc3, abc4]
System.out.println("c2:" + c2);// c2:[abc4, abc5, abc6, abc7]
// c1.remove("abc4");
System.out.println("retainAll:"+c1.retainAll(c2));// retainAll:true
System.out.println("c1:" + c1);// c1:[abc4]
}
}
/**************************************************************************************************************************/
5. Collection集合的遍历:其实就是依次获取集合中的每一个元素。
A:把集合转数组(了解)
/**************************************************************************************************************************/
/* 把集合转成数组,可以实现集合的遍历
* Object[] toArray():返回包含此 collection 中所有元素的数组。元素是任意对象类型,所以是以对象形式接收。
*/
public class CollectionDemo {
public static void main(String[] args) {
// 创建集合对象
Collection c = new ArrayList();
// 添加元素
c.add("hello"); // Object obj = "hello"; 向上转型
c.add((Object)"world");
c.add("java");
// 遍历
Object[] objs = c.toArray();
for (int x = 0; x < objs.length; x++) {
// System.out.println(objs[x]);// hello \n world \n java \n
// 我知道元素是字符串,我在获取到元素的的同时,还想知道元素的长度。
// System.out.println(objs[x] + "---" + objs[x].length());// 错误做法,原因是Object中没有length()方法
// 我们要想使用字符串的方法,就必须把元素还原成字符串
String s = (String) objs[x]; // 向下转型
System.out.println(s + "---" + s.length());// hello---5 \n world---5 \n java---4 \n
}
}
}
/**************************************************************************************************************************/
/*
* 练习:用集合存储5个学生对象,并把学生对象进行遍历。
* 分析:
* A:创建学生类 B:创建集合对象 C:创建学生对象 D:把学生添加到集合
* E:把集合转成数组 F:遍历数组
*/
public class StudentDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
Student s1 = new Student("林青霞", 27);
Student s2 = new Student("风清扬", 30);
Student s3 = new Student("令狐冲", 33);
Student s4 = new Student("武鑫", 25);
Student s5 = new Student("刘晓曲", 22);
c.add(s1); // Object obj = s1; 向上转型
c.add((Object)s2);
c.add(s3);
c.add(s4);
c.add(s5);
Object[] objs = c.toArray();
for (int x = 0; x < objs.length; x++) {
// System.out.println(objs[x]);// cn.cast.Student@15db9742
// 上一行是因为Student类中没重写toStirng()方法
// System.out.println(objs[x].getName());//错误,objs[x]不是Student类型,是Object类型
Student s = (Student) objs[x];
System.out.println(s.getName() + "---" + s.getAge());// 林青霞---27 \n....
}
}
}
public class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
//getXxx()/setXxx()
}
}
/**************************************************************************************************************************/
B:迭代器(集合专用方式)
/**************************************************************************************************************************/
/*
* Iterator<E> iterator():返回在此 collection 的元素上进行迭代的Iterator(迭代器)。集合的专用遍历方式
* E next():返回迭代的下一个元素。抛出:NoSuchElementException - 没有元素可以迭代。
* 不要多次使用it.next()方法,因为每次使用都是访问一个对象。
* boolean hasNext():如果仍有元素可以迭代,则返回 true。
*/
public class IteratorDemo {
public static void main(String[] args) {
// 创建集合对象
Collection c = new ArrayList();
// 添加元素
c.add("hello"); // Object obj = "hello"; 向上转型
c.add((Object)"world");
c.add("java");
// Iterator iterator():迭代器,集合的专用遍历方式
Iterator it = c.iterator(); // Iterator是接口,实际返回的肯定是子类对象,这里是多态
Object obj = it.next();// Object next():获取元素,并移动到下一个位置。
System.out.println(obj);
while(it.hasNext()){
// System.out.println(it.next());// hello \n world \n java \n
// 注意:String类型特殊,若Collection中存的是Object(描述可能有问题,理解就好),上面输出的应该是这样的:cn.cast.Student@15db9742
// System.out.println(it.next().length());// 错误做法,原因是Object中没有length()方法
// it.next()获取的是Object类型,我们要输出String类型,就需要转型。
String s = (String) it.next();// 向下转型
System.out.println(s + "---" + s.length());// hello---5 \n world---5 \n java---4 \n
}
}
}
/**************************************************************************************************************************/
/*
* 练习:用集合存储5个学生对象,并把学生对象进行遍历。用迭代器遍历。
*/
public class IteratorTest {
public static void main(String[] args) {
Collection c = new ArrayList();
Student s1 = new Student("林青霞", 27);
Student s2 = new Student("风清扬", 30);
Student s3 = new Student("令狐冲", 33);
c.add(s1); // Object obj = s1; 向上转型
c.add((Object) s2);
c.add(s3);
Iterator it = c.iterator();
while (it.hasNext()) {
// System.out.println(it.next());// cn.cast.Student@15db9742 是因为Student类中没重写toString()方法
// System.out.println(it.next().getName());//错误,it.next()得到的不是Student类型,是Object类型。
Student s = (Student) it.next();
System.out.println(s.getName() + "---" + s.getAge());// 林青霞---27 \n...
// 注意:不要多次使用it.next()方法。集合中元素是偶数个不会报错(拿到的姓名和年龄对不上),奇数个就会报错。
// System.out.println(((Student) it.next()).getName() + "---" + ((Student) it.next()).getAge());// NoSuchElementException
}
// 使用for循环更好,因为对象是在for循环里面创建的,循环结束 it2 对象就已经是垃圾了,所以它的效率要高
for (Iterator it2 = c.iterator(); it2.hasNext();) {
Student s = (Student) it2.next();
System.out.println(s.getName() + "---" + s.getAge());// 林青霞---27 \n...
}
}
}
public class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
//getXxx()/setXxx()
}
}
/**************************************************************************************************************************/
6. 迭代器
A:是集合的获取元素的方式。
B:是依赖于集合而存在的。
C:迭代器的原理和源码。
a:为什么定义为了一个接口而不是实现类?
b:看了看迭代器的内部类实现。
迭代器使用图解和原理解析:
迭代器的源码:
public interface Interator {
public abstract boolean hasNext();
public abstract Object next();
}
public interface Iterable {
Iterator<T> iterator();
}
public interface Collection extends Iterable {
Iterator<E> iterator();
}
public interface List extends Collection {
Iterator<E> iterator();
}
public class ArrayList implements List {
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
public boolean hasNext() {}
public E next() {} //把 E 看做 Object :public Object next(){}
}
}
//我们每次使用的动作
Collection c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");
Iterator it = c.iterator(); //new Itr();
while(it.hasNext()) {
String s = (String)it.next();
System.out.println(s);
}
7. Collection集合的案例(遍历方式 迭代器)
集合的操作步骤:
A:创建集合对象
B:创建元素对象
C:把元素添加到集合
D:遍历集合
A:存储字符串并遍历
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
public class CollectionDemo {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//创建并添加元素
c.add("hello");
c.add("world");
c.add("java");
//遍历集合
//通过集合对象获取迭代器对象
Iterator it = c.iterator();
while(it.hasNext()) {
String s =(String) it.next();
System.out.println(s);
}
}
}
B:存储自定义对象并遍历
public class Student {
private String name;
private int age;
public Student(){}
public Student(String name,int age) {
this.name = name;
this.age = age;
}
//getXxx()/setXxx()
}
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
public class StudentDemo {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//创建学生对象
Student s1 = new Student("貂蝉", 25);
Student s2 = new Student("小乔", 16);
Student s3 = new Student("黄月英", 20);
Student s4 = new Student();
s4.setName("大乔");
s4.setAge(26);
//添加元素
c.add(s1);
c.add(s2);
c.add(s3);
c.add(s4);
c.add(new Student("孙尚香", 18)); // 匿名对象
//遍历集合
Iterator it = c.iterator();
while(it.hasNext()) {
Student s = (Student)it.next();
System.out.println(s.getName()+"---"+s.getAge());
}
}
}