集合
-
用于存储多个对象,也被称为对象容器
- 集合接口的特点
- 接口中方法
- 接口的实现
- 集合的遍历方式
- 集合相关的接口和相关的实现类位于 java.util 包中
-
泛型
-
安全性高的集合,强制要求集合中的元素统一
-
自定义泛型类---->class 类名{ // E 为泛型标识或泛型标志
//在类中 E 作为一种数据类型直接使用即可—>EKVT都可作为泛型标识
}
-
一个泛型类可以具有有多个泛型标识,以逗号隔开即可—>两个泛型标示的时候,可以都指定,也可以都不指定,但不能只指定一个
-
在创建对象时,每个对象可以根据自身需求指定具体的泛型类型
----> 类名<具体的数据类型> 引用名 = new 类名<具体的数据类型>();
-
不同的对象可以指定不同的数据类型
-
基本数据类型不能作为泛型类型,需要使用其对应的包装类型
-
创建对象时如果没有指定具体的数据类型,则泛型默认为指定的Object类型
-
JDK5.0开始,不仅可以在类上声明泛型(泛型类),也可以在接口上声明泛型(泛型接口)
-
底层设计或是工具类设计时,为了应用层的通用和灵活,通常使用泛型,可以让应用者根据程序的需求给定具体的数据类型,如集合工具类等。但一些常规类不会随着对象的不同而产生不同数据类型需求,不要定义为泛型类
-
-
Collection集合体系—>两个子接口—>存储Object类型的对象
- List—>三个常用实现类—>存储Object类型的对象,有序、有下标、元素可以重复,下标范围0~size-1
- ArrayList—>底层由数组实现,查询效率较高,增删效率相对较低—>JDK1.2版本,线程不安全,并发效率较快
- LinkedList—>底层由链表实现,查询效率相对较低,增删效率相对较高—>JDK1.2版本,线程不安全,并发效率相对较高
- Vector—>底层由数组实现,查询效率较高,增删效率较低—>JDK1.0,线程安全,并发效率低
- Set—>存储任意Object对象,无序、无下标、元素内容不能重复
- HashSet—>一个常用类
- LinkedHashSet—>直接子类—>无下标,但是根据添加顺序进行存储
- SortedSet—>一个接口
- TreeSet—>实现类—>没有下标,可以根据元素内容进行排序
- HashSet—>一个常用类
- List—>三个常用实现类—>存储Object类型的对象,有序、有下标、元素可以重复,下标范围0~size-1
-
Collection : 根接口 ( 父接口 )
- 特点:存储任意类型的多个对象 ( Object )
- 方法:
- ***boolean add(Object obj)***:在集合中添加一个元素,添加成功为true,反之;
- void clear():清空集合中所有的元素
- boolean contains(Object obj):判断集合中是否包含obj,包含为true,反之
- boolean isEmpty():判断集合是否为空,是为true,反之
- int size():获取集合元素的个数
- boolean remove(Object obj):将obj对象从当前集合删除,成功为true,反之
- Object[] toArray():将集合转换为数组
-
List—>Collection的子接口
-
方法:
- 继承于父接口Collection
- void add ( int index , Object obj ):将obj对象插入到当前集合中指定下标位置
- boolean addAll ( int index , Collection c ):将 c 中所有的元素一次性的插入到当前集合指定位置
- ***Object get ( int index )***:获取指定下标对应的元素
- Object set( int index , Object obj):将指定位置的元素修改为obj,被修改的元素作为返回值返回
- Object remove( int index ):删除当前集合中指定位置的元素,被删除的元素作为返回值返回
- List subList( int fromIndex , int toIndex ):从当前集合中截取一个子集合,从fromIndex到toIndex-1
-
实现类—>ArrayList
- ArrayList:底层是数组实现,而且在创建ArrayList对象的时候数组空间并没有给分配,只有第一次调用add方法时(真正使用数组),底层数组空间被分配,初始长度为10,每次扩容到原来的1.5倍
-
遍历方式
-
通过下标获取对应的集合元素,通过变量名操作集合元素
-
for each遍历
for(数据类型 变量名 :要遍历的集合){ //()中的数据类型取决于集合中的泛型类型 // 使用变量名进行操作 }
-
迭代器遍历—>是forEach遍历的底层原理
- Iterator<数据类型> it = 集合名字 . iterator(); //获取一个迭代器对象
- 迭代器泛型类型取决于遍历集合泛型类型
- 迭代器中常见方法
- Boolean hadNext()—>判断迭代器中是否有元素可以操作,有true,反之
- Object next()---->返回迭代器中下一个元素
-
自遍历(JDK8.0)—>default void forEach(Consumer<? super T> action)—>底层原理是forEach
- jdk8.0在List接口中添加了一个default修饰的方法forEach方法
- java.util.function.Consumer接口中只有一个抽象方法accept(Object obj),故是函数式接口可以使用lambda表达式给予实现类,可以定义对元素obj的相关操作。obj类型取决于遍历的集合泛型—>Consumer泛型类型取决于集合的泛型类型
-
排序
- List接口中添加了一个default修饰方法sort(Comparator c)—>Comparator泛型类型取决于操作集合元素的泛型类型
- Comparator位于java.util包中,是一个函数式接口
- Comparator中方法为compare(T t1,T t2):用于定义排序规则—>compare方法中参数类型取决于集合的泛型类型—>指定t1,t2中的比较项,规则为返回1,-1,0
- List接口中添加了一个default修饰方法sort(Comparator c)—>Comparator泛型类型取决于操作集合元素的泛型类型
-
-
-
Set---->Collection子接口
-
方法—>全部继承于父接口Collection中的方法
-
HashSet—>实现类—>保证不重复存储—>HashSet实质为数组+链表
—>覆盖hashCode方法
—>必须保证内容相同的对象返回相同的哈希码值,并且仅让内容相同的返回相同哈希 码值,不同的返回不同哈希码值—>覆盖的做法,将所有属性拼凑为一个int结果 作为返回值返回
—>覆盖equals方法
—>结果为true,代表内容相同,拒绝添加;反之
- HashSet集合中添加元素,默认调用添加元素对应类中hashCode方法,从而获取该对象哈希值,通过哈希码值 % 数组长度 得到一个整数结果,即存储下标,如果存储下标没有元素,则直接将该对象存储在对应下标位置上,但是如果存储下标上已经存在元素,则此时会调用该对象对应类中equals方法,判断当前对象和存储下标位置上元素内容是否相等,equals返回结果为true,则代表内容相同,拒绝添加,反之。—>存储实质为数组+链表
-
遍历方式:forEach、迭代器、自遍历
- LinkedHashSet—>HashSet的子类—>无下标,但是根据添加顺序进行存储
- 如果自定义类型的对象存储LinkedHashSet集合中,保证元素不重复,需要覆盖hashCode和equals方法
- 如果保证元素添加顺序,同时允许内容重复—>ArrayList
- 如果保证元素不重复,顺序无要求—>HashSet
- 如果保证元素添加顺序,不允许元素重复—>LinkedHashSet
- LinkedHashSet—>HashSet的子类—>无下标,但是根据添加顺序进行存储
-
TreeSet—>SortedSet实现类—>Set子接口—>没有下标,可以根据元素内容进行排序
- 如果自定义类型的对象往TreeSet中存储,需要存储对象对应的类覆盖java.lang.Comparable接口,同时覆盖接口中compareTo方法,给予排序规则
- TreeSet的保证元素内容不重复,取决于compareTo方法返回值,当方法返回值为0时,代表内容相同的对象,拒绝添加到集合中
-
-
Map集合体系—>一个接口两个实现类—>用于存储***任意类型键值对***—>***键***无序,无下标,不允许重复(唯一);***值***无序,无下标,允许重复;且Map中都是成对出现的
- HashMap—>直接子类—>JDK1.2版本,线程不安全,并发效率相对较高;允许null作为key、value存在
- LinkedHashMap—>HashMap直接子类—>按照键的添加顺序进行存储
- SortedMap—>Map子接口
- TreeMap—>SortedMap实现类—>自动根据键的内容完成排序
- Hashtable—>直接子类—>JDK1.0版本,线程安全,并发效率相对较慢;不允许null作为key、value存在
- Properties—>Hashtable直接子类—>键和值默认为String类型,使用时不需要加泛型,通常用于读取配置文件
- HashMap—>直接子类—>JDK1.2版本,线程不安全,并发效率相对较高;允许null作为key、value存在
-
Map方法:
- V put ( K key , V value ) —> 往Map集合中添加一个键值对,如果添加的键不存在,则直接将键值对象进行存储,返回null;如果添加键在集合中已经存在,则新Value覆盖旧Value,被替换的Value作为返回值返回—>put可以添加,也可以利用键来***替换(修改)***原有的值内容
- int size ( ) —> 获取Map集合中键值对的个数—>也可以看Map是否为空
- V remove ( K key ) —> 根据Map的键来删除对应的键值对,被删除的Value作为返回值返回
- V get ( K key ) —> 根据Map的键来获取对应的Value
- boolean containsKey ( K key ) —> 判断Map集合中是否包含指定key键,包含true,反之
- boolean containsValue ( V value ) —> 判断Map集合中是否包含指定的Value,包含true,反之
- ***Set keySet()***—>获取Map中所有的键,并返回Set类型的集合
-
实现类
-
HashMap
- JDK1.2版本,线程不安全,并发效率相对较高;允许null作为key、value存在
-
遍历方式
-
键遍历—>通过Map中keySet方法,获取Map中所有的键,存储到Set中,然后通过遍历Set中的键使用Map.get()来获得Value —> Set的泛型取决于Map中键的泛型类型
-
值遍历—>通过Collection values()获取Map中所有的值—>无序无下标故用Collection来存储
—> Collection类型由Map中value决定,且Map中没有提供通过value获取key的方法
-
键值对遍历—>Set<Map.Entry<K,V>> entrySet();—>获取Map中所有的键值对,注意泛型,然后通过Entry中getKey() ; 来获取键;通过Entry中getValue() ; 来获取值
-
自遍历—>JDK8.0提供—>forEach(BiConsumer<? super K , ? super V> action)—>只有一个方法accept,即函数式接口,可以使用lambda表达式—>位于java.util.function.BiConsumer
-
-
原理
- 起初只有两种 —> List和Map—>HashSet即HashMap的key部分,使用Object对象作为value的填充;故HashSet的特点和要求等同于HashMap的键特点和要求
- 如果自定义类型的对象作为HashMap的键,为了保证键的唯一性,自定义的类需要覆盖hashCode和equals。—>往Map中添加一个键值对时,调用键的hashCode方法获取一个哈希码值,再通过计算(哈希码值 % 数组长度)得到一个存储下标,如果存储下标上没有元素,直接将键值对存储;如果存储下标位置上已有内容,则调用键对应类中的equals方法,比较键的内容是否相等。equals方法返回值为true,则新值替换旧值,反之,添加;
-
通常不用自定义类型的对象作为Map的键,通常使用Integer或是String类型
-