Java全栈学习笔记28
# LinkedList
addFirst() 在集合开始插入一个元素
addLast() 在集合的末尾追加元素,相当于add()方法
getFirst() 获取第一个元素
getLast() 获取最后一个
removeFirst() 移除第一个
removeLast() 移除最后一个
LinkedList和ArrayList的区别
#### 底层数据结构
ArrayList:像一个可自动扩容的动态数组。
它在内存中占据一块连续的空间。
当数组容量不足时,会创建一个新的更大数组,并将旧数组的数据拷贝过去(默认是扩容1.5倍)。这个操作比较耗时。
LinkedList:像一个双向链表。
每个元素(节点)都包含三部分:实际数据、指向前一个节点的指针(引用)、指向后一个节点的指针(引用)。
这些节点在内存中不是连续存储的,而是通过指针连接起来
没有容量概念
# Set
实现conllection接口
值不重复
底层存储的是一个HashMap。元素作为HashMap的key
无序。(元素在集合中的排列不是根据插入的顺序)
允许为空,但只能有一个值为null
HashSet:底层存储使用的是HashMap,使用的是equals和hashCode()
TreeSet: 底层存储是使用的是TreeMap
有序的
元素不能为null
元素的类型相同
元素不同使用的compare方法比较。返回0认为元素相同。
Set set = new TreeSet();
//自定义排序规则
Set set2 = new TreeSet(new Compartor(){
public int comparator(Object o1,Object o2){
return
}
})
要求必须要实现Comparable 接口
class com.baor.entity.Student cannot be cast to class java.lang.Comparable (com.baor.entity.Student is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
#### 1. 底层数据结构与顺序
HashSet:
基于 HashMap实现。它使用一个哈希表来存储元素。
元素存储在表中的位置由其 hashCode()值决定。因此,元素没有固定的顺序(既不是插入顺序,也不是大小顺序)。遍历顺序可能因时间而变化(例如,重新哈希后)。
TreeSet:
基于TreeMap 实现。它使用一颗红黑树(Red-Black tree)来存储元素。
红黑树是一种自平衡的二叉搜索树,它会始终维持元素的有序状态。这意味着当你遍历 TreeSet(例如使用 Iterator`)时,元素会按照排序后的顺序(升序)依次返回。
#### 2. 性能对比
HashSet:
操作性能非常高。在理想情况下(哈希函数分散良好,没有太多冲突),add(), remove(), contains()等方法的时间复杂度都是常数时间 O(1)。
性能是它的主要优势。
TreeSet:
由于需要维护树的平衡,add(),remove(),contains() 等方法的时间复杂度为对数时间 O(log n)。
虽然比 HashSet慢,但换来了元素有序的强大功能。它可以非常高效地(O(log n) 或 O(1))进行诸如first(), last(), ceiling(), floor(), headSet(), tailSet() 等有序操作。
#### 3. 元素比较与重复判定
HashSet:
依赖 hashCode()和equals()方法来确定元素是否重复。
先比较哈希值,如果哈希值相同,再使用equals()比较。两个方法必须同时正确重写。
TreeSet:
依赖比较(Comparison)来确定元素的唯一性和位置。
它使用 compareTo()(自然排序)或 compare()(定制排序)方法。如果`compareTo()返回 0,即使 equals() 返回 false,TreeSet 也会认为这两个对象是相等的,从而拒绝添加。这可能会导致与HashSet不一致的行为。
# Map
存储形式--key-v 键值对。
key不可以重复
HashMap、HashTable(保证线程安全,里面的方法存在同步锁)
插入的是无序(元素在集合中的排列不是根据插入的顺序)
key是可以为空
TreeMap
有序(根据key自然顺序)
setValue() 直接声明异常
subMap(fromKey,endKey) 截取,不包含结束位置的key的entry
tailMap(fromKey) 从fromKey位置开始截取到最后
方法 | 描述 | 例子(键集:[5,10,15,20]) |
ceilingKey(K key) | 大于等于key的最小键 | ceilingKey(8)->10 |
floorKey(K key) | 小于等于key的最大键 | floorKey(8)->5 |
higherKey(K key) | 严格大于key的最小键 | higherKey(8)->10 higherKey(10)->15 |
lowerKey(K key) | 严格小于key的最大键 | lowerKey(8)->5 lowerKey(10)->5 |
方法
clear() 清空
put(key,value) key可以是通常是字符串类型,也可以是其它类型
containsKey() key是否存在
containsValue()值是否存在
entrySet() 是把Map集合转换为Set集合
get(key) 根据key获取值
getOrDefault(key,defaultValue) 如果key不存在。则使用默认值。如果key存在,但是值为null,也是使用null 而不是用默认值
keySet() 是把key转换为set集合
putIfAbsent(key,value) 如果key存在,则不插入。否则插入
map集合的遍历方式 3种
通过keySet 遍历
Map maps = new HashMap();
maps.put("age", 12);
maps.put("address", "北京");
maps.put("name", "李四");
for(Object obj : maps.keySet()) {
System.out.println(obj + ":" +maps.get(obj));
}
for(Object obj : maps.values()) {
System.out.println(obj);
}
Set set = maps.entrySet();
for(Object obj : set) {
Map.Entry entry = (Entry) obj;
System.out.println(entry.getKey()+":"+entry.getValue());
}
TreeMap和HashMap的区别
#### 1. 底层数据结构与顺序
HashMap:
基于哈希表(Hash table)原理。它使用键(Key)的 hashCode()值来计算出一个索引位置,将键值对存储在那个位置的桶(Bucket)中。
顺序无关:元素在表中的存储位置由哈希值决定,因此遍历HashMap时,元素的顺序是不可预测的,并且可能随着时间(如重新哈希)而改变。它既不保证插入顺序,也不保证任何排序顺序。
TreeMap:
基于红黑树(Red-Black tree)数据结构。红黑树是一种自平衡的二叉搜索树。
顺序有关:树中的节点会按照键的大小进行排序和存储。这意味着当你遍历 TreeMap(例如使用 Iterator)时,键值对会按照键的排序顺序(默认升序)依次返回。这个顺序是确定且稳定的。
#### 2. 性能对比
HashMap:
在理想情况下(哈希函数分散良好,冲突少),get()和put()等操作的时间复杂度是常数时间 O(1)。
性能是它的主要优势,因为它通过哈希值直接定位元素,无需遍历。
TreeMap:
由于需要维护树的平衡,get(), put(),remove() 等操作的时间复杂度为对数时间 O(log n)。
虽然单次操作比 HashMap慢,但它换来了元素有序的强大功能。它可以非常高效地(O(log n))进行范围查询和有序操作,例如:
firstKey()/lastKey():获取最小/最大键。
lowerKey()/higherKey():获取严格小于/大于某键的键。
ceilingKey()/floorKey():获取大于等于/小于等于某键的键。
subMap(), headMap(), tailMap():获取子映射。
#### 3.null键的支持
HashMap:可以存储一个null键。
TreeMap:不允许 null键。因为它在内部需要调用 compareTo() 或 compare()方法来比较键,而将null与任何对象比较都会抛出 NullPointerException。
#### 4. 比较方式与重复键判定
HashMap:
依赖hashCode()和equals()方法来确定键是否相等。
先比较哈希值,如果哈希值相同,再使用 equals() 比较。两个方法必须同时正确重写。
TreeMap:
依赖比较(Comparison)来确定键的顺序和唯一性。
它使用 compareTo()(自然排序)或 compare()(定制排序)方法。
重要区别:如果 compareTo() 返回 0,TreeMap 就认为这两个键是相等的(即使它们的 equals()方法返回 false),从而会用新的值覆盖旧的值。这可能会导致与 HashMap不一致的行为。
# 迭代器
Iterator
作用遍历集合。
在集合中有一个方法 iterator()获取该集合对象的迭代器,map除外
## 泛型集合
参数化类型。
可以在集合中通过设置泛型,规定集合中只能存储什么数据
泛型只能是引用数据类型