一、集合Collection
1. 集合介绍
变量:表示的内存中的一个空间,只能保存确定类型的单个数据
数组:表示的是内存中的多个连续的空间,这些空间中可以存储多个同类型的数据。
后期继续学习面向对象技术,我们在程序中开始创建对象,使用对象。当在程序中创建的多少越来越多的时候,我们就需要将这些对象也存储起来。
需要存储对象:肯定是需要容器。
变量:可以,要求这个变量必须是引用变量,但只能存储单个对象
数组:可以,但是它要求存储的对象个数是固定的。
字符串缓冲区:不可以,因为它中的数据最后都会被转成字符串。
Java中提供了另外一类容器:集合,它专门负责存储程序中的对象。
开发中使用频率最高的三个集合对象:
ArrayList:
HashSet:
HashMap:
集合是类容器:它也具备了容器最基本的操作方式:
增、删、改、查、判断、遍历。
在Java中设计的集合容器比较多,它们都可以存储对象,但是当对象被存储到这些容器中之后,容器会对其中的对象进行不同的处理。
学习集合的重点:知道每个集合的底层是怎么处理其中存储的对象。知道每个集合的底层数据结构。
由于集合容器太多,需要程序员知道每个集合自己的处理方式,不容易记忆以及使用。于是Java又对这些集合容器的共性操作行为进行的抽取和总结,最后给我们形成了一套所有集合容器都应该具备的基本的操作方式。
Java中定义Collection接口,这个接口中定义了所有集合的共性的操作规则。Java中的所有集合容器都是按照Collection中定义的规则做的实现,我们在开发中只要按照Collection接口中定义的规则,就能够轻易的去操作各个集合容器。
2.Collection接口介绍
Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。此接口 通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。
Collection它是集合体系中的顶层接口。它下面有多个集合容器对象,有些集合可以存放重复的对象,有些不可以,有些可以保证存储的数据的顺序,有些则不可以保证。
Collection接口中定义了集合最共享的操作方式。
3. Collection中的方法介绍
3.1添加方法
add方法是将一个对象添加到集合中容器中,如果添加成功返回true,如果添加失败返回false。
1 /* 2 * 演示Collection接口中的add方法 3 */ 4 public class CollectionAddMethodDemo { 5 public static void main(String[] args) { 6 7 //创建集合容器对象 8 Collection coll = new ArrayList(); 9 //调用添加的方法 10 coll.add("abc"); 11 /* 12 * 能否直接将一个基本类型数据添加到集合中 13 * 将基本类型保存到集合中的时候,只要JDK的版本高于5版本, 14 * 就可以发生自动装箱 15 */ 16 coll.add(123); //自动装箱 ,真正保存的是Integer对象 17 18 coll.add("aaasssdd"); 19 coll.add(new Object()); 20 //打印 21 System.out.println(coll); 22 } 23 }
3.2 删除方法
1 /* 2 * 演示Collection接口中的删除方法 3 */ 4 public class CollectionRemoveDemo { 5 public static void main(String[] args) { 6 7 //创建集合容器对象 8 Collection coll = new ArrayList(); 9 10 //添加元素 11 boolean b = coll.add("abc"); 12 coll.add("abc"); 13 coll.add("itcast"); 14 coll.add("banzhang"); 15 16 System.out.println(b); 17 System.out.println(coll); 18 19 //删除的方法 删除集合中指定的元素,元素存在就会被删除,如果有多个删除其中的第一个 20 boolean b2 = coll.remove("abc"); 21 System.out.println(b2); 22 System.out.println(coll); 23 } 24 }
3.3 判断方法
3.4 获取元素个数
3.5 Collection接口中带All的方法
coll.removeAll(coll2) 从coll中删除coll和coll2两个集合中的相同元素(交集)。
coll.retainAll(coll2) 将coll集合中的 于 coll2 不相同的元素删除(将coll和coll2的交集保留在coll中)。
1 /* 2 * 演示Collection接口中的clear方法 3 */ 4 public class CollectionDemo3 { 5 public static void main(String[] args) { 6 7 //创建集合对象 8 Collection coll = new ArrayList(); 9 10 coll.add("abc"); 11 coll.add("cba"); 12 coll.add("nba"); 13 /* 14 * 将集合中的所有元素删除,但是集合容器依然存在,还可以正常使用 15 * 问题:调用集合的clear方法和 coll = null 的区别? 16 * clear仅仅是情况集合中的元素 17 * coll=null 是将coll引用置为null,它不再指定任何的集合容器 18 */ 19 //coll = null; 20 coll.clear(); 21 System.out.println(coll); 22 coll.add("aaa"); 23 System.out.println(coll); 24 } 25 }
4. 迭代器
4.1 迭代器介绍
由于集合容器较多,并且每个集合容器对保存在其中的元素的处理方式都不同。这样导致不同的集合容器在取出元素的时候都会一定的差异。
Java针对不同的集合容器进行取出元素的共性抽取,得到了一个遍历集合的对象,这个对象被称为迭代器(遍历器)。
迭代器:它的功能就是遍历集合容器的。
遍历容器的规则:需要先判断容器中有没有数据,如果有,就将这个数据取出,如果没有就不用再进行遍历。
Iterator接口,它仅仅是在规定容器应该如何遍历,但是具体的实现类由每个集合容器针对自己存储数据的方式做具体的实现。
而在Collection接口中提供了iterator方法,可以得到不同集合容器自己实现的那个迭代器对象。
4.2 迭代器的使用
1 /* 2 * 演示迭代器的使用 3 */ 4 public class IteratorDemo { 5 public static void main(String[] args) { 6 method2(); 7 } 8 //使用迭代器遍历集合 9 public static void method2() { 10 //创建集合容器对象 11 Collection coll = new ArrayList(); 12 13 //添加元素 14 coll.add("abc"); 15 coll.add("itcast"); 16 coll.add("123"); 17 coll.add("123"); 18 19 //获取迭代器对象 20 Iterator it = coll.iterator(); 21 //使用循环遍历 22 while( it.hasNext() ){ 23 System.out.println(it.next()); 24 } 25 26 /* 27 * 开发中一般使用for循环遍历集合 28 * 注意:当基于集合容器得到一个迭代器对象之后, 29 * 这个迭代器的隐式光标会位于集合的第一个元素的前面, 30 * 如果遍历结束,这时迭代器的隐式光标就已经位于集合中最后一个元素的后面 31 * 这时光标是无法在移动的集合的第一个元素的前面的,如果还需要遍历 32 * 就需要重新基于这个集合容器获取一个新的迭代器 33 */ 34 for( Iterator it2 = coll.iterator() ; it2.hasNext() ; ){ 35 System.out.println(it2.next()); 36 } 37 38 } 39 //演示迭代器的获取 40 public static void method() { 41 42 //创建集合容器对象 43 Collection coll = new ArrayList(); 44 45 //添加元素 46 coll.add("abc"); 47 coll.add("itcast"); 48 coll.add("123"); 49 coll.add("123"); 50 51 //获取迭代器 52 Iterator it = coll.iterator(); 53 54 //判断和取出元素 55 System.out.println(it.hasNext()); 56 System.out.println(it.next()); 57 System.out.println(it.hasNext()); 58 System.out.println(it.next()); 59 System.out.println(it.hasNext()); 60 System.out.println(it.next()); 61 System.out.println(it.hasNext()); 62 System.out.println(it.next()); 63 System.out.println(it.hasNext()); 64 System.out.println(it.next()); 65 } 66 }
4.3 迭代器注意细节
a. 迭代器对象获取到之后,将容器遍历完之后,这个迭代器中的隐式光标就已经移动的集合容器的最后,当前迭代器无法再去遍历集合容器。
b. 在使用迭代器遍历集合容器的时候,不能使用集合自身的增删方法修改集合中的元素。
原因:是因为在获取迭代器的时候,迭代器对象它知道在获取自己的时候,自己需要遍历的集合容器中的元素具体的个数以及存储的细节情况,而在遍历的过程中,如果强行使用集合的增删方法会导致集合中的元素顺序已经存储结构发生变化,但是当前这个迭代器并无法检测到,于是在 正常的遍历过程中就发生 java.util.ConcurrentModificationException。
1 /* 2 * 遍历集合中的元素,判断取出的元素是否是 "abc" 这个字符串,如果是删除 3 */ 4 public static void method3() { 5 //创建集合容器对象 6 Collection coll = new ArrayList(); 7 8 //添加元素 9 coll.add("abc"); 10 coll.add("itcast"); 11 coll.add("123"); 12 coll.add("123"); 13 14 //获取到迭代器对象 15 for( Iterator it = coll.iterator(); it.hasNext() ; ){ 16 //获取到从集合中遍历出来的某个元素数据,并保存到obj引用中 17 Object obj = it.next(); 18 //判断 19 if( obj.equals("abc") ){ 20 /* 21 * 判断成立,说明取出的这个元素一定是"abc"这个字符串,删除 22 * 不能使用集合自身的增删方法对集合中的元素进行操作 23 * 否则会发生异常,如果需要删除集合中的元素,需要使用迭代器自己的删除方法 24 */ 25 //coll.remove(obj); 26 it.remove(); 27 } 28 } 29 System.out.println(coll); 30 31 }
c.在使用迭代器的时候,一般情况下,调用一次hasNext方法,会对应一个next方法。 不建议在遍历集合的时候,在判断完有没有元素之后,在循环中调用多次next方法。容易发生异常
5. 集合的细节
5.1 集合是保存对象的。真正是将对象的内存地址存储在集合容器中。
5.2 如果集合在使用的时候没有添加任何的限制(泛型),这时给集合中保存的任何元素,在存储到集合中之后都会被提升为Object类型。
假设集合中的add方法定义格式:
public boolean add( Object e ){
//.................
}
Collection coll = new ArrayList();
coll.add(“abc”);
当我们在调用add方法的时候,会传递一个具体的对象,但是这个对象会被Object类型的引用接收。
Object e = “abc”; 这里发生了多态,发生了向上转型。
3、 从集合中取出的所有元素,统一都是Object类型,如果想要调用对象自身的特有方法,这时必须使用向下转型。
1 //集合中保存的元素会被提升为Object类型 2 public static void method5() { 3 //创建集合容器对象 4 Collection coll = new ArrayList(); 5 6 coll.add("abc"); //添加了String对象 7 coll.add(123); //添加了一个Integer对象 8 9 //取出元素 10 for (Iterator it = coll.iterator(); it.hasNext();) { 11 Object obj = it.next(); 12 //取出的字符串的长度 13 if( obj instanceof String ){ 14 String s = (String) obj; 15 System.out.println(s.length()); 16 } 17 } 18 }
二、List接口介绍
Collection接口是集合体系中的顶层(根)接口。它中定义的方法是所有集合最共性的操作规则。
但是JDK中不对Collection接口提供直接的实现类,而提供的直接的子接口:
List:列表
List接口下的集合容器都拥有下标(索引),它可以存储重复元素。
Set:视图
Set接口下的集合容器,不能存放重复元素。
List接口:
List接口是Collection接口的子接口,在List接口中继承到了Collection中的所有方法,并且List接口中还增加了围绕集合容器下标(索引)而设计的其他的 增 删 改 查 判断 遍历的方法。
1. List的特有方法
1 /* 2 * List集合中的特有方法 3 */ 4 public class ListDemo { 5 public static void main(String[] args) { 6 7 List list = new ArrayList(); 8 9 //添加方法 10 list.add("aaa"); 11 list.add(1, "abc"); 12 list.add(12); 13 System.out.println(list); 14 15 /* 16 * 删除方法 17 * 如果调用List接口中的remove方法的时候: 18 * 传递的参数是一个int类型的数据,这时这个int类型的数据 19 * 表示的是集合容器的角标(索引),而不会将这个int类型的数据 20 * 自动装箱为Integer对象. 21 */ 22 //list.remove("abc"); 23 //list.remove(12); 24 System.out.println(list); 25 //获取方法 26 System.out.println(list.get(2)); 27 //修改方法 28 list.set(0, "itcast"); 29 System.out.println(list); 30 31 } 32 }
2.List的特有迭代器
由于List接口下的所有集合容器都拥有角标(index),因此List接口除了Iterator迭代器可以迭代集合之外,还提供另外一个List接口专用的迭代器ListIterator。
Iterator迭代器,它只能从前往后遍历集合,一旦遍历结束,迭代器的隐式光标就会位于集合最后一个元素的后面。无法在使用这个迭代器对集合进行迭代。同时迭代的过程中不能使用集合自身的增删等方法对集合修改。而Iterator中仅仅只提供的remove方法,删除集合中的元素。
List接口中提供的ListIterator迭代器,它可以对List集合从前往后遍历,也可以从后往前遍历,同时ListIterator接口中还提供的对集合增 删 改 查 的方法。
1 /* 2 * 演示List接口的特有迭代器 3 */ 4 public class ListIteratorDemo { 5 public static void main(String[] args) { 6 //定义List集合对象 7 List list = new ArrayList(); 8 9 //添加元素 10 list.add("aaa"); 11 list.add("abc"); 12 list.add("cba"); 13 list.add("nba"); 14 list.add("wcba"); 15 list.add("aaa"); 16 17 System.out.println("使用ListIterator正向遍历集合"); 18 //使用List接口特有的迭代器进行遍历 19 ListIterator li = list.listIterator(); 20 while( li.hasNext() ){ 21 System.out.println(li.next()); 22 } 23 24 System.out.println("使用ListIterator逆向遍历集合"); 25 while( li.hasPrevious() ){ 26 System.out.println(li.previous()); 27 } 28 29 } 30 }
3.List集合的迭代
1 /* 2 * 演示List集合的所有遍历方式 3 */ 4 public class ListDemo { 5 public static void main(String[] args) { 6 7 //定义List集合对象 8 List list = new ArrayList(); 9 10 //添加元素 11 list.add("aaa"); 12 list.add("abc"); 13 list.add("cba"); 14 list.add("nba"); 15 16 //使用Iterator遍历 17 System.out.println("使用Iterator遍历"); 18 for( Iterator it = list.iterator() ; it.hasNext() ; ){ 19 System.out.println(it.next()); 20 } 21 //使用ListIterator遍历 22 System.out.println("使用ListIterator遍历"); 23 for( ListIterator li = list.listIterator(); li.hasNext(); ){ 24 System.out.println(li.next()); 25 } 26 //使用普通的for循环提供下标遍历 27 System.out.println("使用普通的for循环提供下标遍历"); 28 for(int i = 0 ; i < list.size() ; i++){ 29 System.out.println(list.get(i)); 30 } 31 /* 32 * 使用foreach遍历 33 * 格式: 34 * for( 容器中元素的类型 变量名 : 容器名 ){ 35 * 变量名中保存的就是从容器中取出的元素 36 * } 37 */ 38 System.out.println("使用foreach遍历"); 39 for( Object obj : list ){ 40 System.out.println(obj); 41 } 42 } 43 }