节制,是比仁慈更高尚的品德。|

subeipo

园龄:1个月粉丝:0关注:0

📂Java
🔖Java
2025-01-19 11:58阅读: 5评论: 0推荐: 0

Java初学者笔记-05、集合框架

集合体系

集合是可变长的。
Collection:代表单列集合,每个元素包含一个值。
Map:代表双列集合,每个元素包含两个值。

Collection集合

集合体系

  1. List系列集合:添加的元素是有序、可重复、有索引
  • ArrayList、 LinekdList:有序、可重复、有索引。
  1. Set系列集合:添加的元素是无序、不重复、无索引
  • HashSet: 无序、不重复、无索引;
  • LinkedHashSet:有序、不重复、无索引。
  • TreeSet:按照大小默认升序排序、不重复、无索引。

常用功能与遍历

Collection常用功能

方法名 说明
public boolean add(E e) 把给定的对象添加到当前集合中
public void clear() 清空集合中所有的元素
public boolean remove(E e) 把给定的对象在当前集合中删除
public boolean contains(Object obj) 判断当前集合中是否包含给定的对象
public boolean isEmpty() 判断当前集合是否为空
public int size() 返回集合中元素的个数。
public Object[] toArray() 把集合中的元素,存储到数组中

遍历方式

迭代器遍历

迭代器遍历,集合遍历的专用方式。

Collection<String> names = new ArrayList<>();
Iterator<String> it = names.iterator();
it.next();
while(it.hasNext()){
it.next();
}

迭代器初始位置为容器位置为0处,调用next()取出当前位置数据并移到下个位置。调用hasNext()判断当前位置有无数据,并移到下个位置。

增强for循环遍历

既可以遍历数组,也可以遍历集合。本质是迭代器的简化写法。快捷写法是.for

for(元素的数据类型 变量名:数组或者集合){
}
Collection<String> c = new ArrayListe();
// c.for
for(String s : c) {
System.out.println (s);
}
Lambda表达式遍历

default void forEach(Consumer<? super T> action)

Collection<String> lists = new ArrayList<>();
lists. forEach(new Consumer<String>() {
@Override
public void accept (String s) {
System.out.println(s);
}
});
// 使用lambda表达式
lists.forEach(s -> {System.out.println(s);});
// 简化
lists.forEach(s -> System.out.println(s));
// 方法引用简化(没必要到这一步)
lists.forEach(System.out::println);
三种遍历方式的区别
认识并发修改异常问题

遍历集合的同时又存在增删集合元素的行为时可能出现业务异常,这种现象被称之为并发修改异常问题。
解决方案1:删除操作后i--
解决方案2:倒着遍历并删除(前提是支持索引)

三种遍历方式能否解决并发修改异常

遍历方案1:迭代器也存在并发修改异常问题会直接抛异常,不要用集合的remove()去删,而是用迭代器的remove()去删。
遍历方案2和3:增强for和Lambda都不行。

List

List的特有方法

方法名称 说明
void add(int index,E element) 在此集合中的指定位置插入指定的元素
E remove(int index) 删除指定索引处的元素,返回被删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素

ArrayList的底层原理

底层基于数组存储数据。
数组的特点:

  • 查询速度快(注意:是根据索引查询数据快):按照索引查询任意数据耗时相同
  • 增删数据效率低:可能要把后面的数据前移;可能要复制数组到更大的数组中。
  • 第一次扩容为10,第二次扩容15。扩容到原来的1.5倍

LinkedList的底层原理

底层基于双向链表存储数据。
链表的数据是一个一个独立结点组成,在内存中不连续,每个结点包含数据值和下一个结点的地址。
链表的特点:

  • 查询慢,无论查询那个数据都要从头开始。
  • 链表增删相对较快。
    双向链表的特点:
  • 对首尾元素进行增删改查的速度是极快的。
  • 可以设计队列和栈。

针对这些特点,LinkedList新增了很多首尾操作的特有方法。

方法名称 说明
public void addFirst(E e) 在该列表开头插入指定的元素
public void addLast(E e) 将指定的元素追加到此列表的末尾
public E getFirst() 返回此列表中的第一个元素
public E getLast() 返回此列表中的最后一个元素
public E removeFirst() 从此列表中删除并返回第一个元素
public E removeLast() 从此列表中删除并返回最后一个元素

独有功能不要用多态。

Set

Set要用到的常用方法,基本上就是Collection提供的!!自己几乎没有緩外新增一些常用功能!
特点:无序,不重复,无索引
HashSet:无序、不重复、无索引。
LinkedHashSet: 有序、不重复、无索引。
TreeSet:排序(大小升序排)、不重复、无索引。

HashSet的底层原理

基于哈希表存储数据的。
哈希值:int类型的随机值,Java中每个对象都有一个Hash值。可以调用Object类提供的hashCode方法,返回该对象自己的哈希值。
不同的对象的哈希值大概率不相等,但有可能会出现哈希碰撞。
JDK8之前,哈希表=数组+链表。
JDK8开始,哈希表=数组+链表+红黑树。
哈希表是一种增删改查数据,性能都很好的数据结构。

底层原理
  1. HashSet创建一个默认长度16的数组,默认加载因子为0.75,数组名为table
  2. 使用元素的哈希值对数组的长度做运算,计算出应存入的位置。
  3. 判断当前位置是否为null,如果是null直接存入。
  4. 如果不为null,表示有元素,先调用equals方法比较。不相同,形成链表。
  5. JDK8之前,新元素占老元素位置,老元素挂下面;JDK8开始,新元素挂老元素下面。
扩容机制
  1. 整个哈希表长度超过长度×加载因子,就进行扩容以维护性能。扩容到原来的两倍,第一次32.
  2. JDK8之后,当链表长度超过8,且数组长度≥64,自动将链表转换成红黑树,提高检索性能。
缺点
  1. 占内存。
  2. 不能重复。
  3. 没有索引。

如果希望Set集合认为2个内容相同的对象是重复的应该怎么办?

  • 重写对象的hashCode和equals方法。

LinkedHashSet集合的底层原理

有序,无重复,无索引。
底层依然基于哈希表:数组+链表+红黑树 实现的。
但是,它的每个元素都额外多了一个双链表的机制记录它前后元素的位置。

TreeSet集合的底层原理

一定要排序,无重复,无索引。
底层基于红黑树实现。给一个数据就要排序.
注意:

  • 对于数值类型:Integer,Double,默认按照数值本身的大小进行升序排序。
  • 对于字符串类型:默认按照首字符的编号升序排序。
  • 对于自定义类型如Student对象,TreeSet默认是无法直接排序的。
TreeSet的自定义排序

对于自定义对象,如何解决排序?

  1. 对象类实现一个comparable比较接口,重写compareTo方法,指定大小比较规则。
  2. public TreeSet (Comparator c)集合自带比较器Comparator对象,指定比较规则。
  3. 规定:如果左边大于右边 请返回正整数。
  4. 按照规则的比较数据进行重复判定,比如两个学生的age是相等的,treeset会去掉一个。

Map集合

需要存储一一对应的数据时,就可以考虑使用Map集合来做。
Map集合的所有键是不允许重复的,但值可以重复,键和值是一一对应的,每一个键只能找到自己对应的值。
Map集合体系

  • HashMap(由键决定特点):无序、不重复、无索引;(用的最多)。键值对可以为null。
  • LinkedHashMap(由键决定特点):由键决定的特点:有序、不重复、无索引。
  • TreeMap(由键决定特点):按照大小默认升序排序、不重复、无索引。
Map<String,Integer> map = new HashMap<>(); //经典代码
map.put("111",100);

Map集合的常用功能

方法名称 说明
public V put(K key,V value) 添加元素
public int size() 获取集合的大小
public void clear() 清空集合
public boolean isEmpty() 判断集合是否为空,为空返回true,反之为false
public V get(Object key) 根据键获取对应值
public V remove(Object key) 根据键删除整个元素
public boolean containsKey(Object key) 判断是否包含某个键
public boolean containsValue(Object value) 判断是否包含某个值
public Set keySet() 获取全部键的集合
public Collection values() 获取Map集合的全部值

Map集合的遍历方式

键找值遍历

先获取Map集合全部的键,再通过遍历键来找值。

方法名称 说明
public Set keySet() 获取所有键的集合
public V get(Object key) 根据键获取其对应的值

键值对整体遍历

把键值对看成一个整体Set进行遍历。

Map提供的方法 说明
Set<Map.Entry<K, V>> entrySet() 获取所有""键值对""的集合
Map.Entry提供的方法 说明
K getKey() 获取键
V getValue() 获取值
for (Map. Entry<String, Double> entry : entries) {
String key = entry.getKey() ;
double value = entry.getValue():
System.out.println(key + "====>" + value);

Lambda表达式遍历

JDK 1.8开始之后的新技术(非常的简单)。

方法名称 说明
default void forEach(BiConsumer<? super K, ? super V> action) 结合lambda遍历Map集合
map. forEach((k, v) -> {
System.out.println(k + "—----" + v);
});

本文作者:subeipo

本文链接:https://www.cnblogs.com/subeipo/p/18679467/java-chu-xue-zhe-bi-ji05-ji-he-kuang-jia

版权声明:本作品采用署名—非商业性使用—相同方式共享 4.0 协议许可协议进行许可。

posted @   subeipo  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起