一些关于java集合的知识点
集合与数组的区别
- 长度区别
- 数组固定
- 集合可变
- 内容区别
- 数组可以是基本类型,也可以是引用类型
- 集合只能是引用类型
- 元素区别
- 数组只能存储同一种类型
- 集合可以存储不同类型(一般存储一种类型——泛型)
Collection集合的方法
- Boolean add(E e):在集合末尾添加元素
- Boolean remove(Object o):若本类集中有值与相等的元素,则删除该元素,并返回true
- void clear():清除本类集中所有的元素,调用完该方法后本类集将为空
- Boolean contains (Object o ):判断集合中是否包含某元素
- Boolean isEmpty():判断集合是否为空
- int size():返回集合中的元素个数
- Boolean addAll(Collection c):将一个类集c中的所有元素添加到另一个类集
- Object[ ] toArray():返回一个包含了本类集合中所有元素的数组,数组类型为,Object[ ]
- Iterator iterator():迭代器,集合的专用遍历方式
常用集合的分类
- Collection接口的接口,对象的集合(单列集合)
- List接口:元素按进入先后有序保存,可重复
- LinkedList接口实现类,链表,插入删除,没有同步,线程不安全
- ArrayList接口实现类,数组,随机访问,没有同步,线程不安全
- Vertor接口实现类数组,同步,线程安全
- set接口:仅接受一次,不可重复,并做内部排序
- HashSet使用hash表(数组)存储元素
- LinkedHashSet链表维护元素的插入次序
- TreeSet底层实现为二叉树,元素好排序
List和Set集合详解
list和set的区别
- 有序性
- List保证按插入顺序排序
- Set存储和取出顺序不一致
- 唯一性
- List可以重复
- Set元素唯一
- 获取元素
- List可以通过
- Set不能根据索引获取元素
list
特有功能:
- void add(int index,Object obj):在指定位置添加元素
- Object remove(int index):根据指定索引删除元素,并把删除的元素返回
- Object Set(int index,Object obj):把指定索引位置的元素修改指定的值,返回修改前的值
- int indexOf(Object o):返回指定元素在集合中第一次出现的索引
- Object get(int index):获取指定位置的元素
- ListIterator listItertor():列表迭代器
- List subList(int fromIndex,int toIndex):截取集合。
-
ArrayList:底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素
-
LinkedList 底层数据结构是链表,查询慢,增删快,线程不安全,效率高,可以存储重复元素
- 添加:addFirst() addLast()
- 删除:removeFirst()removeLast()poll()pollFirst() pop()//弹出最后一个
- 获取:getFirst() getLast
-
Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素
- public void addElement(E obj)相当于add()
- public E elementAt(int index)相当于get()
- public Enumeration
elements( ) 相当于iterator()
-
如何避免并发修改异常?// ConcurrentModificationException
- 在使用迭代器或者增强for遍历集合的过程中,不要使用集合的方法去添加或者删除元素即可。
泛型
-
泛型接口的两种使用方式:
- 实现类给出具体的类型
- 实现类延续泛型,创建实现类对象时再确定类型
-
泛型不具备继承性,但数据具备继承性
import java.util.ArrayList; public class GenericsDemo02 { public static void main(String[] args) { ArrayList<Ye> list1 = new ArrayList<>(); ArrayList<Fu> list2 = new ArrayList<>(); ArrayList<Zi> list3 = new ArrayList<>(); // 调用method方法 // method(list1); // method(list2);//报错 // method(list3);//报错 list1.add(new Ye()); list1.add(new Fu()); list1.add(new Zi()); } public static void method(ArrayList<Ye> list) { } } class Ye { } class Fu extends Ye { } class Zi extends Fu { }
此时可以使用泛型的通配符:
- ?也可以表示不确定类型可以进行类型的限定
- ?extends E:表示可以传递E或者E所有的子类类型
- ?super E:表示可以传递E或者E所有的父类类型
public static void method(ArrayList<? extend Ye> list) //关于Ye的子类都可以使用泛型方法
应用场景:
- 如果在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。
- 如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以使用泛型的通配符
泛型的通配符:
- 关键点:可以限定泛型的范围
泛型总结
- 什么是泛型
- JDK5引入的特性,可以再编译阶段约束操作的数据类型,并进行检查
- 泛型的好处
- 统一数据类型
- 把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为再编译阶段类型就能确定下来。
- 泛型的细节?
- 泛型中不能写基本数据类型
- 指定泛型的具体类型后,传递数据时,可以传入该类型和他的子类类型
- 如果不写泛型,类型默认时Object
- 哪里定义泛型?
- 泛型类:再类名后面定义泛型,创建该类对象的时候,确定类型
- 泛型方法:再修饰符后面定义方法,调用该方法的时候,确定类型
- 泛型接口:在接口名后面定义泛型,实现类确定类型,实现类延续泛型
set
-
Set系列集合的特点
- 无序、不重复、五索引
- Set集合的方法上基本与Collection的API一致
-
Set集合的实现类特点
- HashSet:无序、不重复、无索引
- LinkedHashSet:有序、不重复、无索引
- TreeSet:可排序、不重复、无索引
-
(1)HashSet底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。
/*
具体实现唯一性的比较过程:存储元素首先会使用hash()算法函数生成一个int类型hashCode散列值,然后已经的所存储的元素的hashCode值比较,如果hashCode不相等,则所存储的两个对象一定不相等,此时存储当前的新的hashCode值处的元素对象;如果hashCode相等,存储元素的对象还是不一定相等,此时会调用equals()方法判断两个对象的内容是否相等,如果内容相等,那么就是同一个对象,无需存储;如果比较的内容不相等,那么就是不同的对象,就该存储了,此时就要采用哈希的解决地址冲突算法,在当前hashCode值处类似一个新的链表, 在同一个hashCode值的后面存储存储不同的对象,这样就保证了元素的唯一性。
*/
-
覆盖hashCode()方法的原则:
1、一定要让那些我们认为相同的对象返回相同的hashCode值
2、尽量让那些我们认为不同的对象返回不同的hashCode值,否则,就会增加冲突的概率。
3、尽量的让hashCode值散列开(两值用异或运算可使结果的范围更广)
- LinkedHashSet底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。
小结
/*
Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只 是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素。
*/
List和Set总结
-
List,Set都是继承自Collection接口,Map则不是
-
List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉
-
Set和List的对比:
- Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
- List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
-
ArrayList与LinkedList的区别和适用场景
-
Arraylist:
优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。 -
优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景
缺点:因为LinkedList要移动指针,所以查询操作性能比较低。
-
map
-
map遍历的三种方式
-
先获取所有的键,把这些键放到一个单列的集合当中,在用循环取出值:map.keySet()方法
-
直接用map.entrySet()取出键值对,然后遍历取出键和值,entry.getKey(),entry.getValue();
-
lambda表达式
map.forEach(new BiConsumer<String, String>() { @Override public void accept(String key, String value) { System.out.println(key+"="+value); } });
-
-
HashMap的特点
- HashMap是Map里面的一个实现类
- 没有额外需要学习的特有方法,直接是使用Map里面的方法就可以了
- 特点都是由键决定的:无序、不重复、无索引
- HashMap跟HashSet底层原理是一摸一样的,都是哈希表结构
- 依赖hashCode方法和equlas方法保证键的唯一
- 如果键存储的是自定义对象,需要重写hashCode和equals方法如果值存储自定义对象,不需要重写hashCode和equals方法
-
LinkedHashMap的存和取的顺序是一致的。
-
TreeMap集合的特点是怎么样的?
- 不重复、无索引、可排序
- 底层基于红黑树实现排序,增删改查性能较好
-
TreeMap集合排序的两种方式
- 实现Comparable接口,指定比较规则
- 创建集合时传递Comparator比较器对象,指定比较规则
-
treemap添加元素的时候,键是不需要重写hashcode和equals方法的
-
在hashmap的底层,默认是利用哈希值的大小关系来创建红黑树的,不需要实现compareable接口或者传递比较器对象
-
一般不形成长链表的情况下,hashmap的效率比treemap要高
-
在map集合中,putIfAbsent方法是如果键重复了,也不会覆盖的方法。 代码中的逻辑都有两面性,如果我们只知道了其中的A面。而且代码中还发现了有变量可以控制的两面性的发生。那么该逻辑一定会有B面。
-
如何选择三种双列集合?
默认:HashMap(效率最高)
如果要保证存取有序:LinkedHashMap
如果要进行排序:Treemap
可变参数
-
可变参数本质上就是一个数组
-
作用:在形参中接受多个数据
-
格式:数据类型... 参数名称
举例:int... a
-
注意事项:
- 形参列表中可变参数只能有一个
- 可变参数必须放在形参列表的最后面
Collections
-
addAll 批量添加元素
-
shuffle 打乱元素
ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"abc","bcd","qwer","df","asdf","1234"); Collections.shuffle(list);
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)