菜单
本页目录
第6单元  集合类

数组缺点:只能存放,长度固定、类型统一的数据。

6.1   集合概述
1、定义:Java提供的特殊类:能存储任意类型对象、长度可变的类。
2、位置:java.util包中(此包使用前需导入)
3、分类:按存储结构分为2类:(1)单列集合Collection;(2)双列集合Map
(1)单列集合Collection:单列集合类的根接口
         1) 作用:存储满足某种规则的元素
         2) 2个子接口:List接口:元素有序且可重复
                                   Set接口 :元素无序且不重复
         3)实现类:List接口实现类:ArrayList类、LinkedList类
                            Set接口实现类:HashSet类、TreeSet类

(2)双列集合Map:双列集合类的根接口
         1) 作用:存储键(Key)值(Value)映射关系的元素
                          每个元素是一个键值对,可以通过指定的Key找到对应的Value。
         2)实现类:HashMap类、TreeMap类

             
6.2   Collection接口
1、定义:单列集合的根接口
2、单列集合(List和Set)通用方法:
(1)add():添加一个元素;(2)addAll():添加所有元素
(3)clear():清除所有元素;(4)remove():删除指定元素;(5)removeAll():删除指定所有元素
(6)isEmpty():判断集合是否为空;
(7)contains():判断集合是否包含某个元素;(8)containsAll():判断集合是否包含所有元素
(9)Iterator iterator():返回该集合的迭代器(Iterator对象),用于该集合元素遍历
(10)int size():返回集合元素个数
            注意:开发中,直接使用Colletion接口很少,基本使用其子接口:List接口、Set接口、Queue接口和SortedSet接口。


6.3   List接口

6.3.1   List接口简介
1、定义:List接口继承自Collection接口。
2、元素特点:(1)元素有序,可重复;
                       (2)元素存入顺序和取出顺序一致。
3、存储方式:线性方式存储
4、访问:索引访问
5、方法:
(1)继承Collection接口方法
(2)List接口针对索引的特有方法:
1)void add(int index,Object element):指定位置添加一个元素;
2)boolean addAll(int index,Collection c):指定位置添加集合所有元素
3)Object get(int index):返回指定索引处的元素
4)Object remove(int dex):删除指定索引处的元素
5)Object set(int index,Object element):将指定索引处的元素,替换成element对象并返回
6)int indexOf(Object o):返回对象第在集合中第一次出现的索引值
7)int lastIndexOf(Object o):返回对象第在集合中最后一次出现的索引值
8)List subList(int fromIndex,int toIndex):返回指定长度的子集合。[左索引,右索引)

注:List接口,可以通过ArrayList类和LinkedList类实现。

6.3.2   ArrayList集合
1、定义:ArrayList类是List接口的一个实现类,内部封装一个长度可变的数组对象。
             (当存入的元素超过数组长度,分配更大的数组存储元素)
2、方法:
(1)void add([int index,]Object element):在指定位置存储元素
(2)Object get(int index):根据指定位置,读取元素
(3)int size():获取元素个数
3、特点:
(1)不适合大量的增加或删除操作:Array List集合底层使用数组保存元素,增加或删除元素会创建新的数组对象,效率低。
(2)适合查找和读取元素:通过索引访问元素。效率高。

6.3.3   LinkedList集合
1、定义:LinkedList类是List接口的另一个实现类,内部封装一个双向循环列链表,
                链表中的每个元素使用引用记住其前后元素。(当存入或删除元素,只需要修改元素之间的引用关系)
2、针对元素添加和删除,Linked List类特有方法:
(1)void add([int index,]Object element):在指定位置,存储元素
(2)void addFirst(Object element):在集合开头,插入此元素
(3)void addLast(Object element):在集合结尾,插入此元素
(4)void getFirst():返回集合第一个元素
(5)void getLast():返回集合最后一个元素
(6)void removeFirst():删除集合第一个元素
(7)void removeLast():删除集合最后一个元素
3、特点:
(1)适合大量的增加或删除操作:只需修改元素间的引用关系,效率高。

6.3.4   iterator接口
          Iterator接口是集合中的一员;
           Collection接口和Map接口,用于存储元素;
           而Iterator接口,用于迭代访问Collection集合中的元素(即遍历Collection集合元素)
           Iterator对象,被称为迭代器。

1、定义:用于迭代访问Collection集合中的元素(即遍历Collection集合元素),Iterator对象被称为迭代器。
2、迭代器遍历集合元素需要使用的方法:
(1)iterator():Collection类对象,调用iterator()方法,返回该集合迭代器
(2)hasNext():集合迭代器调用hasNext()方法,判断集合是否存在下一个元素。
(3)next():集合迭代器调用next()方法,返回该元素,且该元素是Object类型。
3、Iterator迭代器遍历元素过程:
(1)集合迭代器创建后,迭代器指针(hasNext())位于集合第一个元素之前,不指向任何元素。
(2)当集合迭代器第一次调用next()方法后,迭代器指针(hasNext())的索引向后移动一位,
        指向第一个元素并返回该元素。
(3)直到hasNext()返回false,遍历结束。
              
          注意:迭代器遍历集合元素,返回的元素类型是Object类型,若要改变类型,需强制转换类型。
 
4、迭代器遍历集合元素时,不可以使用集合本身remove()方法
(1)原因:迭代器预期迭代次数发生改变,出现并发修改异常
(2)解决方法:
1)在删除语句后面,添加break语句;
2)使用迭代器本身的remove()方法,替换掉集合的remove()方法。
 (原因:迭代器本身删除方法导致的迭代次数变化,对于预期本身来说是可预期的)


6.3.5   foreach循环
1、定义:语法更简洁的for循环,增强for循环。
2、特点:没有循环条件,没有迭代语句,自动遍历容器中的元素。
3、作用:只能遍历集合或数组的元素,不能修改集合或数组的元素
4、语法格式:
for(容器中元素类型 临时变量: 容器变量){
         执行语句;
}
      foreach循环次数:由容器中元素的个数决定
      每次循环时,临时变量保存当前循环的元素

5、缺点:只能遍历元素,不能修改元素。
原因:临时变量=“字符串”(把临时变量指向了一个新的字符串,与原数组没有关系)


6.4   Set接口

6.4.1   Set接口简介
1、定义:Set接口继承自Collection接口。
2、元素特点:(1)元素无序,不可重复;
                       (2)元素存入顺序和取出顺序不一致。
3、方法:继承Collection接口方法
4、实现类:
(1)HashSet类:依据对象的散列值确当元素在集合中的存储位置
                             具有良好的存储和查找功能。
(2)TreeSet类:以二叉树的方式存储元素,能对元素进行排序。

6.4.2   HashSet集合
1、定义:HashSet类是Set接口的一个实现类。
2、特点:(1)元素无序且不可重复
                (2)元素存取顺序不一致
3、方法:
4、HashSet集合元素不重复原因:
      在调用add()方法,添加元素时
(1)先调用对象的hashCode()方法,获得对象散列值,根据散列值计算元素存储位置。
(2)如果该位置没有元素,直接存入元素;
         如果有元素,调用对象的equals()方法比较当前存入的元素依次与该位置上的元素比较:
          若返回false,存入该元素;否则,说出元素重复,舍弃该元素。

     因此,在向HashSet集合存入元素(对象)时,需重写Object类中hasdCode() 方法和equals()方法。 
   (String类已经重写,不需要自己再重写一遍;但自定义的对象存入时,必须重写Object类中hasdCode() 方法和equals()方法)  

5、LinkedHashSet类:
(1)定义:LinkedHashSet类是HashSet类的子类。
(2)作用:1)元素无序且不可重复
                   2)元素存取顺序一致
(3)特点:使用双向链表维护内部元素关系。

6.4.3   Treeset集合
1、定义:TreeSet类是Set接口的另一个实现类。。
2、特点:元素不可重复,自动排序
3、方法:
4、TreeSet集合元素自动排序的原因:
(1)自然排序:实现Comparable接口并重写compareTo()方法
         被添加的元素的类实现了Comparable接口(基本类型包装类,String类都自动实现该接口),
         Comparable接口强行对现实它的每个类的对象整体排序。
         Comparable接口的compareTo()方法:自然比较法。

     因此,在向TreeSet集合存入元素(对象)时,需实现Comparable接口并重写compareTo()方法,以实现自动排序功能。
   (基本类型包装类和String类已经重写,不需要自己再重写一遍;但自定义的对象存入时,必须实现Comparable接口并重写compareTo()方法)

(2)比较器排序:实现Comparator接口并重写compare()方法(equals()方法Object类已有,不需要重写)


6.5   Map接口

6.5.1   Map接口简介
1、定义:双列集合的根接口,每个元素包含一个键对象Key和值对象Value。
             (键值对存在对应关系,即映射。在Map集合中,指定Key,即可以找到对应Value)
                Map接口中,键必须唯一,不能重复。如果存储相同的键,键相同,值覆盖
2、双列集合Map接口常用方法:
(1)void put(Object key,Object value):添加元素(存储键值对)
(2)Object get(Object key):根据指定的键Key,返回对应的值;若不存在映射关系,返回null
(3)void clear():清除所有元素(键值对);
(4)V remove(Object key):根据键名,删除对应值,并返回被删除的值
(5)int size():返回集合元素(键值对)个数
(6)boolean containsKey(Object key):判断指定的键是否有对应的值
(7)boolean containsValue(Object value):判断指定的值是否有一个或多个键映射
(8)Set keySet():返回包含键的Set视图
(9)Collection<V> values():返回包含值的Collection视图
(10)Set<Map,Entry<K,V>> entrySet():返回包含映射关系的的Set视图
           
6.5.2   HashMap集合
1、定义:HashMap类是Map接口的一个实现类,用于存储键值对。
2、特点:(1)键不重复:键相同,值覆盖
                (2)键值对无序:元素存取顺序不一致。
3、方法:继承自Map接口方法
4、遍历Map中,所有的键值对:2种方法
(1)先遍历Map集合中所有的键,再根据键获取对应的值。
1)HashMap map=new HashMap():创建Map集合对象
2)Set keySet=map.keySet():调用Map对象的keySet()方法,返回所有键的Set集合
3)Iterator it=keySet.iterator():创建Set集合迭代器
4)hasNext(),next(),get(key):对集合进行遍历,获取对应值

(2)先获取集合中所有的键值对,然后从键值对中取出键和值。
1)HashMap map=new HashMap():创建Map集合对象
2)Set entrySet=map.entrySet():调用Map对象的entrySet()方法,返回所有映射的Set集合
                                                        (此元素类型是Map.Entry类型,Entry是Map内部接口)
3)Map.Entry entry= (Map.Entry)it.next():遍历得到的元素是Object类型,所以需强制转换成Map.Entry类型
4)Object key=entry.getKey()                   :获取Entry对象中的键和值。
5)Object Value=entry.getValue()

5、LinkedHashMap类:
(1)定义:LinkedHashMao类是HashMap类的子类。
(2)作用:1)键不重复:键相同,值覆盖
                   2)键值对有序:元素存取顺序一致。
(3)特点:使用双向链表维护内部元素关系。


6.5.3   TreeMap集合
1、定义:TreeMap类是Map接口的另一个实现类。。
2、特点:(1)键不重复:键相同,值覆盖
                (2)(键值对)元素按键值自动排序
3、方法:
4、TreeMap集合元素按键值自动排序的原因:
(1)自然排序:实现Comparable接口并重写compareTo()方法
         被添加的元素的类实现了Comparable接口(基本类型包装类,String类都自动实现该接口),
         Comparable接口强行对现实它的每个类的对象整体排序。
         Comparable接口的compareTo()方法:自然比较法。

     因此,在向TreeSet集合存入元素(对象)时,需实现Comparable接口并重写compareTo()方法,以实现自动排序功能。
   (基本类型包装类和String类已经重写,不需要自己再重写一遍;但自定义的对象存入时,必须实现Comparable接口并重写compareTo()方法)

(2)比较器排序:实现Comparator接口并重写compare()方法(equals()方法Object类已有,不需要重写)

6.5.4   Properties集合
           Map接口还有一个实现类Hashtable类,Hashtable线性安全,即存取元素速度很慢。
           但Hashtable类的子类Properties在实际应用中很重要。
1、定义:存储字符串类型的键和值
2、作用:存取应用的配置项。
3、常用方法:
(1)Properties p=new Properties():创建Properties对象
(2)setProperty(String key, String value):添加字符串类型键值
(3)Enumeration names=p.propertyNames():Properties对象调用propertyNames()方法,返回包含键的Enumeration对象
(4)getProperty(String key):通过指定键,返回对应值


6.6   泛型

6.6.1   泛型概述
1、定义:在使用强类型编程语言是,定义的一些可变部分。
2、作用:在定义时,用泛型替代实际类型,通过实际调用传入的类型对泛型进行替换,实现代码复用。
3、特点:相对于传统形参,泛型使得参数具有更多类型(泛型类、泛型对象,泛型接口,泛型方法),更好地复用代码。
4、组成:泛型的声明:尖括号(<>)和类型形参,两部分组成。

6.6.2   泛型类和泛型对象
1、泛型类定义:在类定义时,通过一个标识表示类的某个属性的类型或者某个方法的返回值和参数类型。
                   只有在用户使用该类时,该类所属的类型才能明确。
2、泛型类声明语法:
[访问权限] class 类名<泛型标识1,泛型标识2,...,泛型标识n>{
           [访问权限]  <泛型标识> 变量名;
           [访问权限]  <泛型标识> 方法名(泛型标识 变量名);                     //抽象方法
           [访问权限]  <泛型标识> 返回值类型 方法名(泛型标识 变量名){};  //成员方法
}
3、创建泛型对象语法:
类名<参数化类型> 对象名=new 类名<参数化类型>();

6.6.3   泛型方法
1、泛型方法定义:在类中可以定义泛型方法,泛型方法与其所在的类是否时泛型类无关。
2、泛型方法声明语法:
 [访问权限]  <泛型标识>返回值类型  方法名(泛型标识 变量名){};
}

6.6.4   泛型接口
1、定义:定义泛型接口
2、泛型接口声明语法:
[访问权限] interface 接口名<泛型标识>{
           [访问权限]  <泛型标识> 变量名;
           [访问权限]  <泛型标识> 方法名(泛型标识 变量名);                     
}

例子:
interface Info<T>{
      public T getVar();
}
3、泛型接口子类的定义:
(1)直接在子类实现的泛型接口中指定泛型具体参数类型
(2)在子类的定义上声明泛型类型:在子类不确定泛型参数类型时使用

6.6.5   类型通配符
1、协变:父类与子类可以保持相同形式的变化
      数组可以保持协变,但集合不能协变
2、Java泛型解决集合协变:类型通配符:?
3、使用类型通配符:?接收泛型对象,则该对象只能接受,不能修改。


6.7   Lambda表达式
1、定义:Lambda表达式是由参数列表、箭头符号(->)和函数体组成(函数体:表达式或语句块。  表达式:会被执行,返会执行结果;语句块:语句依次执行)
2、作用:取代大部分匿名函数,适用于集合遍历和其他集合操作
3、特点:极大优化代码结构(JDK提供了大量的内置函数式接口)
4、常用语法:
(1)()->System.out.println("Hello Lambda!");         无参数,无返回值
(2)(x)->System.out.println(x);                                有参数,无返回值
(3)x->System.out.println(x);                                   只有一个参数,小括号可缺省
(4)Comparator<Integer> com=(x,y)->{System.out.println("函数式接口");return Integer.compare(x,y)}   有参数,有返回值;语句块有多条语句
(5)Comparator<Integer> com=(x,y)->Integer.compare(x,y);                   有参数,有返回值;语句块只有一条语句,return和大括号都可以缺省
(6)(Integer x,Integer y)->Integer.compare(x,y);                                        Lambda表达式参数列表类型可以缺省,由JVM通过上下文推断类型