场景
当数据多了要进行存储时,需要一个容器,存储固定长度的数据可以使用数组。但是如果数据的个数不确定,再使用数组就较为繁杂。Java就引入了另外一个可变的容器 ---- 集合
在1.2版本之后,随着功能和需求的增多,将其不同种类的共性向上抽取,形成了体系,就出现了集合框架,有了更多种类的集合容器,用来完成不同的需求。这些集合容器是通过数据结构(存储数据的一种方式)来进行区分。集合框架的最顶层是一个接口collection(最基本的共性)。
1 数组和集合的区别
(1)数组的长度是固定的,集合的长度是可变的
(2)数组中存储的是同一类型数据,集合存储的都是对象
2 接口(collection)
Collection 层次结构 中的根接口。集合是将多个元素组成一组对象,这些对象也称为 collection 的元素。
特点:
集合的长度没有限制,可以存放任意多的元素,而且元素的数据类型也可以不同。
2.1 调用Collection不带All的方法
// Collection是一个接口类型的容器,不可创建对象。只能通过多态创建对象Collection coll = new ArrayList();
// 添加对象coll.add("coco");coll.add("xiaoran");coll.add("nana");
// 移除对象coll.remove("nana");
// 接口重写toString方法,输出集合内容(toString可省略)System.out.println(coll.toString()); // 结果:[coco, xiaoran]
// isEmpty();判断集合是否为空。空---true,不为空---falseSystem.out.println(coll.isEmpty()); // 结果:false
// contains(object o);判断集合是否包含指定的元素System.out.println(coll.contains("coco")); // 结果:false
// size();返回此 collection 中的元素个数System.out.println(coll.size()); // 结果:2
// clear();格式化,移除此 collection 中的所有元素(可选操作)coll.clear();System.out.println(coll.toString()); // 结果:[]
2.2 调用Collection集合带All的方法
public static void main(String[] args) {// 创建两个集合容器Collection coll1 = new ArrayList();Collection coll2 = new ArrayList();// 向两个容器添加元素coll1.add("abc1");coll1.add("abc2");coll1.add("abc3");coll2.add("abc3");coll2.add("abc4");coll2.add("abc5");//(1)addAll(Collection c);将集合2所有元素添加到集合1中coll1.addAll(coll2); // 输出集合结果:[abc1, abc2, abc3, abc3, abc4, abc5]//(2)containsAll(Collection c);如果集合1包含集合2所有元素,则返回 true。boolean b = coll1.containsAll(coll2); System.out.println(b); // 结果:true//(3)removeAll(Collection c);移除集合1中和集合2的相同元素boolean c = coll1.removeAll(coll2); System.out.println(c); // 结果:true 输出集合结果:[abc1, abc2]//(4)retainAll(Collection c);保留集合1中和集合2的相同元素boolean d = coll1.retainAll(coll2); System.out.println(d); // 结果:true 输出集合结果:[]// 输出集合容器System.out.println(coll1); // 结果:[]System.out.println(coll2); // 结果:[abc3, abc4, abc5]}
3 集合的取出方式(接口Iterator)
由于集合框架中每个集合容器存储方式不同,就需要建立不同的遍历方法。但是我们的目的是一个一个的取出元素,java引入了迭代器机制,来对不同集合元素的进行遍历。
迭代:无论是什么数据结构,最终的取出方式就是一个个的取,取之前先判断,有就取一个,没有就结束了
(1)hasNext()方法,如果迭代器对象中有元素,则返回true ,反之false
(2)next()方法,返回迭代的下一个元素
public static void main(String[] args) {// 1.创建集合对象Collection c = new ArrayList();c.add("abc1");c.add("abc2"); // 2.取出集合中的元素,// 集合中有iterator方法通过集合获取迭代器对象Iterator it = c.iterator();// 3.使用迭代器对象的方法来获取集合中的元素// System.out.println(it.next());// System.out.println(it.next());// 3.1改进方法(1)while循环(2)for循环。后者更加节省空间// 方法一:while循环while(it.hasNext()){System.out.println(it.next());}System.out.println("===============");// 方法二:for循环for (Iterator it1 = c.iterator(); it1.hasNext();) {System.out.println(it1.next());}
}
4 集合的细节问题
(1)集合存储的是什么
(2)集合可以存储基本数值吗?
(3)怎么调用某个具体对象的特有方法?
public static void main(String[] args) {Collection c = new ArrayList();/** c.add("abc1");* 1 集合中存储的是什么?其实存储的都是对象的地址*//* c.add(1);* 2 集合中可以存储基本数值吗?不可以,只能是对象。* 但是jdk1.5引入自动装箱之后可以直接写,* 但其底层存储还是对象(基本数据类型包装类对象)* 等价于c.add(Integer.valueOdd(1));*//** 3 往集合中存元素,迭代到的元素都是Object对象。* 需要使用到集合中某个具体对象的本身方法时,就需要Object对象向下转型*/c.add("tan1");c.add("zhou2");for (Iterator it = c.iterator(); it.hasNext();) {// 想打印集合中字符串的长度length();Object obj = it.next();// 想要使用字符串的方法 ,需要向下转型成String对象String str = (String)obj;System.out.println(str.length());//结果:4 5 }
5 重写equals()方法
(1)源码
(2)测试类
为什么要重写equals()方法?
从集合的定义可知,集合中存储的是对象。一些collection允许有重复的元素,而另一些则不允许。
但是无论学生的名字和年龄是否相同,每次创建对象后的地址都是不相同的。
我们想要的是只要同姓名,同年龄一样,这两个对象就是相等的。
判断两个对象是需要通过equals()方法进行比较,因此我们可以自定义比较方法方法。重写equals()方法,建立自己比较的依据。类似于String对象的equals(),只要内容相同即可。
注意:List允许有重复的元素,重复指的是两个对象相等。coll.add()里面传入同一个引用变量叫重复。如果是创建两个对象,对象的名字和年龄相同不叫重复。因此此处要重写equals()方法,使其符合逻辑。即当姓名和年龄相同的对象才叫重复。