一、集合概述
1、什么是集合?
通俗来讲,集合就是把具有同一性质的一类东西汇聚成一个整体。从字面意思理解,集合就是把具有相同性质的一类东西汇聚成一个整体。在面向对象中,对事物都是以对象的形式体现。为了方便对多个对象的操作,需要存储多个对象的容器,而集合就是存储多个对象最常用的一种方式。
集合框架:用于存储数据的容器。
集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。
任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。
集合的主要操作:
1、将对象添加到集合
2、从集合中删除对象
3、从集合中查找到对象
4、从集合中修改对象
2、集合和数组的区别
1、数组是固定长度的;集合可变长度的。
2、数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。
3、数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型。
数组 | 集合 | |
---|---|---|
容器 | 是 | 是 |
大小 | 一旦创建,它的大小是固定的 | 集合大小是一直可变的 |
数据 | 基本类型 | 、引用类型 |
类型 | 数组中存储的数据类型是相同的 | 集合可以存储任意类型的对象 |
3、集合框架的好处
- 容量自增长;
- 提供了高性能的数据结构和算法,使编码更轻松,提高了程序速度和质量;
- 允许不同 API 之间的互操作,API之间可以来回传递集合;
- 可以方便地扩展或改写集合,提高代码复用性和可操作性。
- 通过使用JDK自带的集合类,可以降低代码维护和学习新API成本。
4、集合框架
(1) Java集合框架的接口
接口 | 特点 |
---|---|
Collection | 集合的根接口,没有实现类,用于引用子接口的对象,Collection是一组对象的集合 |
List | 元素之间是有序的,元素可以重复。 通过索引来访问元素,允许在指定位置插入元素 |
Set | 元素之间是无序的,元素不可重复 |
Map | 存储Key/Value对的集合 key值不允许重复,每个key最多只能映射到一个值。Map是一组Key/Value对的集合。 |
(2)Java集合框架的实现类
接口 | 实现类 | 特点 |
---|---|---|
LIst | ArrayList | 底层使用数组实现,长度默认是10。如果集合元素的个数超出当前数组大小,则创建新的扩容60%的数组,并将原来的元素拷贝过来。由于数组是按内存位置依次序存放,因此查找快,但是增删元素涉及到后面的元素移动,因此增删元素慢 |
LinkedList | 底层使用链表实现。增删元素时,链表只需增加或删除一个结点,这样的增删效率较高,但查询时需要一个一个的遍历,所以查询速率较低。 | |
Vector | 和ArrayList原理相同,Vector是线程安全的,所以效率略低。 | |
Set | HashSet | 底层是以哈希表实现的,所有元素是按hashCode的值存放的,HashSet是线程不安全的,存取速度快 |
TreeSet | 底层使用红-黑树的数据结构实现。 要求元素实现Compareable接口,默认树元素进行自然排序(String)。 |
|
LinkedHashSet | 底层使用链表技术实现,但是结合了哈希值实现存储。LinkedHashSet的增删效率高,查询效率低 | |
LIst | ArrayList | 底层使用数组实现,长度默认是10。如果集合元素的个数超出当前数组大小,则创建新的扩容60%的数组,并将原来的元素拷贝过来。由于数组是按内存位置依次序存放,因此查找快,但是增删元素涉及到后面的元素移动,因此增删元素慢 |
LinkedList | 底层使用链表实现。增删元素时,链表只需增加或删除一个结点,这样的增删效率较高,但查询时需要一个一个的遍历,所以查询速率较低。 | |
Vector | 和ArrayList原理相同,Vector是线程安全的,所以效率略低。 | |
Map | HashMap | 底层是哈希表存储。 HashMap没有对key排序,可以存入null键、null值。 HashMap是线程不安全的。 |
TreeMap | 底层是哈希表存储。 TreeMap 对key进行排序,要求key实现Compareable接口 |
|
HashTable | 底层是哈希表数据结构。 HashTable是线程安全的,不可以存入null键和null值。 HashTable效率较低,已被Hash Map替代 |
|
LinkedHashMap | 底层使用链表技术实现,但是结合了哈希值实现存储。 LinkedHashMap的增删效率高,查询效率低。 |
(3)应用场景
为什么有这么多集合?因为每一个容器对数据的存储方式不同,为各种存储方式提供了多样化的选择
Collection | 这是一个纯粹的接口,用于引用List、Set的实现对象 |
---|---|
List | 如果需要保留存储顺序,并且允许保留重复的元素,使用List接口的实现类。 如果查询较多,使用ArrayList。 如果存取较多,使用LinkedList 如果需要线程安全,使用Vector |
Set | 如果不需要保留存储顺序,并且需要去掉重复的元素,使用Set接口的实现类 如果需要将元素排序,使用TreeSet 如果不需要排序,使用HashSet比使用TreeSet效率高 如果我们需要保留储存顺序,又要过滤重复元素,使用LinkedHashSet |
Map | 如果需要保留key/value形式数据,使用Map接口的实现类 如果我们需要将元素排序,使用TreeMap 如果不排序,HashMap的效率高于TreeMap |
二、Collection
Collection是一个集合接口,为集合对象提供了最大化的统一操作方式。集合类都是在java.util包中,因此Collection接口就是java.util.Collection。
Collection没有实现类,通常用于对实现子接口的对象引用。
Collection coll=new ArrayList();
1.基本操作
add(Object o) | 向集合添加元素。成功返回true,失败返回false |
---|---|
remove(Object o) | 删除指定元素。成功返回true,失败返回false |
size() | 获取集合中元素的个数 |
clear() | 清空集合中的所有元素 |
isEmpty() | 判断集合是否为空 |
contains(Object o) | 判断集合是否包含指定对象 |
注意:contains内部依赖equals方法进行比较 |
2.迭代器
java实现了迭代器iterator对象,它提供了一些方法实现了对集合中元素的遍历》Collection接口中定义了获取迭代器的方法(iterator() ),所有的Collection类型的集合都可以通过这个方法获取自身的迭代器
(1) Iterator接口
该接口就是迭代器接口,定义了常见的迭代方法:
boolean hasNext() | 判断集合中是否有下一个元素,如果有元素就返回true,没有返回true |
---|---|
E next() | 返回集合中的下一个元素,注意:如果没有下一个元素时,调用next()方法会抛出NoSuchElementException异常 |
void remove() | 从集合中移除迭代器返回的最后一个元素(可选操作) |
(1)迭代器遍历相关操作
while循环
最常见的iterator遍历方式
Collection<String> list=new ArrayList<String>();
list.add("str1");
list.add("str2");
list.add("str3");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
String str = iterator.next();
System.out.println(str);
}
for循环
一般不使用
Collection<String> list=new ArrayList<String>();
list.add("str1");
list.add("str2");
list.add("str3");
for (Iterator<String> it= list.iterator(); it.hasNext();){
String str = it.next();
System.out.println(str);
}
使用迭代器清空集合
Collection<String> list=new ArrayList<String>();
list.add("str1");
list.add("str2");
list.add("str3");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
iterator.next();
iterator.remove();
}
注意:
1、如果迭代器已经指向集合的末尾,如果再调用next()返回NoSuchElementException 异常。
2、在使用remove()之前必须使用next()方法
3、在对集合进行迭代过程中,不允许出现对元素的非迭代器操作,因为这样会产生安全隐患。在集合遍历中,使用迭代器操作集合对象时,又使用集合其它API操作集合时,将会抛出并发修改异常(ConcurrentMo dificationException>。
三、List
List是一个有序的集合,它按元素加入到集合中的顺序依次摆放。注意:不是按集合中对象的属性排序,而是按插入位置的顺序
List的特点:
1、元素有序
2、元素有下标
3、元素可重复
4、遍历时存入顺序和取出顺序一致
1、特有方法
增加 | void add(int index,E element | 指定位置添加元素 |
boolean addAll(int index,Collection c) | 指定位置添加集合 | |
修改 | E set(int index,E element) | 返回的时需要替换的集合中的元素 |
删除 | E remove(int index) | 删除指定位置的元素 |
获取 | E get(int index) | 获取指定下标的元素,注意IndexOutOfBoundsException |
int indexOf(Object o) | 找到该元素第一次出现的下标,找不到返回-1 | |
int lastIndexOf(Object o) | 找到该元素最后一次出现的下标,找不到返回-1 | |
List subList(index fromIndex,int toIndex) | 求子集和,[fromIndex,toIndex) | |
迭代 | listIterator() |
(1) 常用功能
List<String> list=new ArrayList<>();
list.add("str1");
list.add("str2");
list.add("str3");
list.add("str4");
list.add(1,"str5");//把元素添加到指定位置
System.out.println("集合中的元素为"+list);
String s = list.get(0); //根据索引获取元素
//使用get方法遍历集合
for (int i = 0; i < list.size(); i++) {
String s1 = list.get(i);
System.out.println(s1);
}
list.set(3, "str333"); //替换指定位置的元素
list.remove(0); //删除指定位置的元素
int indexOf = list.indexOf("str1"); //元素第一次出现的下标
int index= list.lastIndexOf("str"); //元素最后一次出现的下标
List<String> subList = list.subList(1, 3);//子集
(2)ListIterator
ListIterator是list集合特有的迭代器,支持在迭代过程添加和修改元素
hasPrevious() | 判断是否存在上一个元素 |
---|---|
previous() | 当前指针先向上移动一个单位,然后取出当前指针指向的元素 |
next() | 先取出当前指针指向的元素,然后指针向下移动一个单位 |
add(E e) | 把元素插入到当前指针指向的位置上 |
set(E e) | 替换迭代器最后依次返回的元素 |
代码示例:
List<String> list=new ArrayList<>();
list.add("str1");
list.add("str2");
list.add("str3");
list.add("str4");
ListIterator<String> iterator = list.listIterator(); //返回的是一个List接口中特有的迭代器
System.out.println("是否存在上一个元素:"+iterator.hasPrevious());
iterator.next();
System.out.println("获取上一个元素:"+iterator.previous());
iterator.set("ss"); //替换迭代器最后一次返回的元素
while (iterator.hasNext()){//向后遍历
String value = iterator.next();
System.out.println(value);
iterator.add("s"); //遍历时添加元素
}
while (iterator.hasPrevious()){//向前遍历
System.out.println(iterator.previous());
}
(3)集合遍历
List<String> list=new ArrayList<>();
list.add("str1");
list.add("str2");
list.add("str3");
list.add("str4");
//get方法遍历
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
}
//forEach遍历
for (String value:list
) {
System.out.println(value);
}
//迭代器遍历
ListIterator<String> iterator = list.listIterator(); //获取到迭代器
while (iterator.hasNext()){
String value = iterator.next();
}
2、ArrayList
在实际开发中,ArrayList是使用频率最高的一个集合实现类
(1) 原理
ArrayList底层维护了一个Object[ ]数组用于存储对象,默认数组的长度是10。当默认的或者指定的容量不够存储对象的时候,容量自动增长为原来容量的1.5倍。
由于底层使用数组实现,在增加和删除的时候会牵扯到数组的增容和拷贝元素,所以效率比较慢。但是数组可以直接按索引查找元素,所以查找时比较快。
3、LinkedList
(1)原理
由于LinkedList在底层使用链表实现存储结构,需要让上一个元素记住下一个元素,所以每个元素中保存的有下一个元素的位置。虽然LinkedList中也有下标,但是查找的时候需要从头往下找,显然没有数组查找快。但是链表在插入新元素的时候,只需让前一个元素记住新元素,新元素记住下一个元素,所以插入较快
(2)特有方法
addFirst(E e) | 增加到集合最前面 |
---|---|
addLast(E e) | 增加到集合最后面 |
getFirst() | 获得集合中的第一个元素 |
getLast() | 获得集合的最后一个元素 |
removeFirst() | 移除集合中第一个元素,如果没有 |
removeLast() | 移除集合中最后一个元素,如果没有 |
descendingIteratort() | 返回逆序的迭代器对象 |
4、Vector
Vector是一个线程安全的集合。它和ArrayList特性相似,较少使用
(1) 特有方法
void addElement(E obj) | 在集合末尾添加与那苏 |
---|---|
E elementAt(int index) | 返回指定下标的元素 |
Enumeration elements() | 返回集合中所有的元素,封装到Enumeration对象中 |
四、set
1、Set
set元素是无序存放的,即元素存入和取出的顺序不一定相同,并且集中中的元素不能重复。其中HashSet是一种常用的Set。
Set的特点
1、Set中的元素无序,但可以排序
2、Set中的元素无下标
3、set中的元素不可重复
(1) 存储原理
Set中的对象不是按元素加入到集合中的先后顺序依次摆放的,因此Set中没有索引,也不能按索引访问集合中的对象。
在Set内部的存储结构使用了散列算法,按对象的散列值决定存放的位置,也按照散列值检索对象。由于散列值的无序特点,因此Set的行为表现为一个无序的集合。
原理总结:
1、HashSet调用对象的hashCode()方法得到对象的hashCode值,并依据hashCode值确定该对象在HashSet中存放的位置
2、HashSet判断两个对象是否相等的依据:两个对象通过equals()方法比较结果为相等,并且两个hashCode()方法得到对象的hashCode值也相等
3、规则:如果相隔对象通过equals()方法比较结果为相等,那么两个对象的hashCode()方法得到的hashCode值也应该相等
(2)重复元素
在java中,重复元素使用Object类中得hashCode和equals判断。在类中重写了hashCode和equals,当两个得hashCode和equals返回相同值并且equals返回true时,两个对象相等。
常见重复元素
1、所有null常量都是重复元素
2、相同对象得不同引用变量是重复元素
3、两个String对象得值相同时,认为这两个对象是重复的
2、HashSet
使用Set 集合都是需要去掉重复元素的。如果在存储的时候逐个equals()比较,效率较低,哈希算法提高了去重复的效率,降低了使用equalst)方法的次数。当HashSet 调用add()方法存储对象的时候,先调用对象的 hashCode()方法得到一个哈希值,然后在集合中查找是否有哈希值相同的对象,如果没有哈希值相同的对象就直接存入集合,如果有哈希值相同的对象,就和哈希值相同的对象逐个进行equals(]比较,比较结果为 false就存入,true则不存入。
3、TreeSet
Treeset是 Sortedset接口的唯一实现类,Treeset可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。
所有加入TreeSet的元素必须实现Comparable接口,否则会抛出异常,在Treeset内部使用comparable接口对元素排序。和 Hashset相比,它的效率较低。
int compareTo(Object o) | 大于返回正数,等于返回零,小于返回负数 |
---|
4、LinkedHashSet
LinkedHashset是具有可预知迭代顺序的set接口的哈希表和链接列表实现。此实现与HashSet的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序。
五、Map
在集合框架中,Map于Collection是并列存在的,相互没有继承关系
Map的特点:
1、采用key/value的形式存储数据
2、Map中key不可重复
3、各个键值对无序
4、各个键值对无下标
1、Map
(1)基本操作
Map是一种按照键(key)存储元素的容器,键(可以)可以是任意类型的对象,所有value按key存储和获取
V put( K key,V vlue) | 按key增加value。如果Map中已经有相同的key,则返回以前的对象,并使用value覆盖原来的对象 |
---|---|
putAll(Map<? extends K,? extends V> m | 将参数m中的所有key/value对加入到集合中 |
remove(key) | 删除key对应的key/value对 |
value get(key) | 按key获取value,如果没有匹配到key则返回null |
dear() | 清空集合对象 |
boolean isEmpty() | 判断集合中是否有元素,有则返回true,没有返回false |
int size() | 返回Map中key/value对的个数 |
boolean containsKey(Object key) | 判断集合中是否包含指定的key |
boolean containsValue(Object value) | 判断集合中是否包含指定的value |
(2)遍历操作
Set keySet() | 获得所有key组成的Set集合 |
---|---|
Collection values() | 获取所有values组成的集合 |
Set<Map.Entry<k,v>> entrySet() | 获取所有Map.Entry组成的集合。 Map.ENtry由key、value组成,通过getKey、getValue获取键和值 |
使用keySet
这是最常用的Map迭代实现方式
将key转成Set集合(keySet()),通过迭代器取出Set集合中的每一个key,再通过key获取对应的value。
代码示例:
Map<String,Integer> map=new HashMap<>();
map.put("Tom", 18);
map.put("Jack", 30);
map.put("Will", 25);
Set<String> set = map.keySet();
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
String key = iterator.next();
Integer value = map.get(key);
System.out.println(key+" "+value);
}
使用values()
Map<String,Integer> map=new HashMap<>();
map.put("Tom", 18);
map.put("Jack", 30);
map.put("Will", 25);
Collection<Integer> values = map.values();
Iterator<Integer> iterator = values.iterator();
while (iterator.hasNext()){
Integer value = iterator.next();
System.out.println(value);
}
使用Map.Entry对象
Map<String,Integer> map=new HashMap<>();
map.put("Tom", 18);
map.put("Jack", 30);
map.put("Will", 25);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
while (iterator.hasNext()){
Map.Entry<String, Integer> entry = iterator.next();
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+": "+value);
}
2、HashMap
HashMap是使用最广泛的Map实现,它的底层是哈希表数据结构实现存储,不支持多线程同步,可以存入null键,null值。
HashMap<String,String> hashMap=new HashMap<>();
hashMap.put(null, null);
hashMap.put("张三", "成都");
hashMap.put("李四", "大理");
hashMap.put("王二", "兰州");
System.out.println(hashMap);
3、LinkedHashMap
LinkedHashMap底层使用链表实现
LinkedHashMap<String,String> hashMap=new LinkedHashMap<>();
hashMap.put(null, null);
hashMap.put("张三", "成都");
hashMap.put("李四", "大理");
hashMap.put("王二", "兰州");
System.out.println(hashMap);
4、TreeMap
HashMap中的所有数据都是无序存放的,在TreeMap中按照key进行排序。要求key必须实现Comparable接口,具体要求见TreeSet中的实现要求
六、工具类
1、Collections
Collections不是Collection接口的实现类,它是一个工具类,其中所有方法都是静态的。
(1)List集合操作
功能 | 方法 | 描述 |
---|---|---|
二分查找 | int binarySearch(list,key) | 集合中都是Comparable的实现类且元素都要按升序排列 |
排序 | sort(list) | 集合中元素都是Comparable的实现类 |
顺序反转 | reverse(list) | |
强行逆转 | Comparator reverseOrder(Comparator) | 按Comparator比较方式逆转 |
位置交换 | swap(list,x,y) | 按索引位置交换 |
元素替换 | replaceAll(list,old,new) | 如果被替换的元素不存在,那么原集合不变 |
(2) 其它工具方法
最大值 | max(Collection) max(Collection,comparator) |
---|---|
最小值 | min(Collection) min(Collection,comparator) |
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。