【Java集合一】集合概述

一、集合简介

Java 集合框架(Collection Framework)是 Java 提供的一组用于存储和操作对象的类和接口集合。这些集合类提供了不同的数据结构,使得数据的管理和操作更加方便和高效。

Java 集合框架提供了各种类型的数据结构,如列表(List)、集合(Set)、映射(Map)等,以便开发人员能够更有效地管理和操作数据。

Java集合大致框架图如下:

具体关系图如下:

Collection 接口的接口 对象的集合(单列集合)
├——- List 接口:元素按进入先后有序保存,可重复
│—————-├ LinkedList 接口实现类, 基于链表, 优势在于插入删除,线程不安全
│—————-├ ArrayList 接口实现类, 基于数组, 优势在于随机访问,线程不安全
│—————-└ Vector 接口实现类 ,基于数组,线程安全
│ ———————-└ Stack 是Vector类的实现类
└——- Set 接口: 仅接收一次,不可重复,并做内部排序
├—————-└ HashSet 使用hash表(数组)存储元素
│————————└ LinkedHashSet 链表维护元素的插入次序
└ —————- TreeSet 底层实现为二叉树,元素排好序
└——- Queue 接口: 队列,通常用于存储和处理元素的顺序。
│—————-├ LinkedList 接口实现类, 链表, 优势在于插入删除, 线程不安全
│—————-├ PriorityQueue 接口实现类, 优先级队列, 不允许空值, 线程不安全
Map 接口 键值对的集合 (双列集合)
├——— Hashtable 接口实现类,线程安全
├——— HashMap 接口实现类 ,线程不安全
├——— ConcurrentHashMap 接口实现类 ,线程安全
│—————–├ LinkedHashMap 双向链表和哈希表实现
│—————–└ WeakHashMap
├ ——– TreeMap 红黑树对所有的key进行排序
└——— IdentifyHashMap

1.1 Collection 接口

Collection 是最基本的集合接口,声明了适用于JAVA集合(只包括Set和List)的通用方法。

Collection接口的方法:
  • boolean add(Object o); //向集合中加入一个对象的引用
  • void clear(); //删除集合中所有的对象,即不再持有这些对象的引用
  • boolean isEmpty(); //判断集合是否为空
  • boolean contains(Object o); //判断集合中是否持有特定对象的引用
  • boolean remove(Object o); //从集合中删除一个对象的引用
  • int size(); //返回集合中元素的数目
  • Iterartor iterator(); //返回一个Iterator对象,可以用来遍历集合中的元素
  • Object[] toArray(); //返回一个数组,该数组中包括集合中的所有元素
  • Stream stream(); //返回一个以集合为源的流,jdk1.8新加的

二、List

List 接口是 Collection 接口的子接口,表示一个有序的集合,允许存储重复元素。List 接口的实现类提供了按索引访问元素、插入元素、删除元素等操作,是一种常用的数据结构。

主要特点:
  • 有序性:List 接口维护了元素的插入顺序,可以按照元素在列表中的位置来访问和操作元素,插入的顺序即输出的顺序。
  • 允许存储重复元素:与 Set 不同,List 允许在列表中存储相同的元素。
  • 允许元素为空:可以插入多个null元素。
  • 可通过索引访问元素:List 接口提供了根据索引访问元素的方法,例如 get(int index) 和 set(int index, E element)。
List接口主要提供了以下方法:
  • void add(int index, E element) :在指定索引位置插入元素。
  • E get(int index) :获取指定索引位置的元素。
  • E set(int index, E element) :将指定索引位置的元素替换为新的元素。
  • int indexOf(Object o) :返回指定元素在列表中第一次出现的索引。
  • int lastIndexOf(Object o) :返回指定元素在列表中最后一次出现的索引。
  • E remove(int index) :移除指定索引位置的元素。
List的接口有三个实现类。
  • ArrayList:基于数组实现的 List,适合随机访问元素
    • 优点: 底层数据结构是数组,查询快,增删慢。
    • 缺点: 线程不安全(一般不考虑到线程的安全因素,用Arraylist效率比较高)
  • LinkedList:基于链表实现的 List,适合频繁插入、删除操作。
    • 优点: 底层数据结构是链表,增删快,查询慢。
    • 缺点: 线程不安全。
  • Vector:线程安全的 List,较少在现代代码中使用。
    • 优点: 底层数据结构是数组,查询快,增删慢。线程安全。
    • 缺点: 效率低(相比 ArrayList 线程不安全的,性能会稍慢一些)。

2.1 ArrayList

ArrayList 是 Java 中的 List 接口的一个常见实现类,它基于数组实现动态数组,可以根据需要动态增加其大小。ArrayList 提供了一系列方法来操作元素,是 Java 集合框架中最常用的数据结构之一。ArrayList 线程不安全。

特点和优势
  • 动态数组:ArrayList 内部使用数组来存储元素,可以根据需要动态增加其大小,而不需要手动处理数组扩容的问题。
  • 按索引访问:由于基于数组实现,ArrayList 可以通过索引快速访问元素,具有良好的随机访问性能。
  • 允许存储重复元素:与 Set 不同,ArrayList 允许在列表中存储相同的元素。
  • 允许元素为空:可以插入多个null元素。
  • 易于使用:ArrayList 提供了丰富的操作方法,如添加元素、删除元素、获取元素等,使用方便。
构造方法:
  1. ArrayList() :创建一个空的 ArrayList,当第一次add时才会初始化初始容量为 10。
  2. ArrayList(int initialCapacity) :创建一个具有指定初始容量的 ArrayList。
  3. ArrayList(Collectionc) :使用指定 collection 中的元素来构造一个 ArrayList。

示例代码:

import java.util.ArrayList;
import java.util.List;public class ArrayListExample {public static void main(String[] args) {List<String> fruits = new ArrayList<>();fruits.add("Apple");fruits.add("Banana");fruits.add("Orange");System.out.println("Size of the list: " + fruits.size());fruits.remove(1);for (String fruit : fruits) {System.out.println(fruit);}}
}

2.2 LinkedList

LinkedList 是 Java 中 List 接口的另一个常见实现类,它使用双向链表实现数据存储。与 ArrayList 基于数组实现不同,LinkedList 通过节点之间的引用来连接各个元素,适合频繁插入、删除操作的场景。LinkedList 线程不安全。

特点和优势:
  • 双向链表:LinkedList 内部使用双向链表来存储元素,每个节点包含对前一个和后一个元素的引用,便于在列表中进行插入和删除操作。
  • 插入和删除效率高:由于基于链表实现,插入和删除操作的效率比较高,不需要像数组那样涉及数据的搬移。
  • 支持高效的迭代:LinkedList 实现了 List 接口和 Queue 接口,可以作为队列或栈来使用,并且支持高效的迭代操作。
  • 占用更多内存:相比于 ArrayList,LinkedList 的每个节点都需要额外的空间存储指向前后节点的引用,可能占用更多的内存
构造方法:
  1. LinkedList() :创建一个空的 LinkedList。
  2. LinkedList(Collectionc) :创建一个包含指定集合中的元素的 LinkedList,这样就可以通过将现有集合传递给构造函数来初始化 LinkedList。

示例代码:

import java.util.LinkedList;
import java.util.List;public class LinkedListExample {public static void main(String[] args) {List<String> animals = new LinkedList<>();animals.add("Dog");animals.add("Cat");animals.add("Elephant");System.out.println("Size of the list: " + animals.size());animals.remove(1);for (String animal : animals) {System.out.println(animal);}}
}

三、Set

Set 接口继承自 Collection 接口,因此它具有 Collection 接口定义的大部分方法,同时又添加了不能包含重复元素的特性。

特点和优势:
  • 不包含重复元素:Set 中不允许包含重复的元素,每个元素在 Set 中都是唯一的。
  • 允许空元素:允许一个空元素。
  • 无序性:Set 不保证元素的顺序,即元素存储的顺序和插入的顺序不一定相同,但可以使用特定的实现类如 TreeSet 来维护元素的排序状态。
  • 常用实现类:Java 中常见的 Set 接口的实现类包括 HashSet、TreeSet 和 LinkedHashSet。
  • 用途广泛:由于其元素不重复的特性,Set 通常用于需要确保元素唯一性的场景,例如去重操作、查找某个元素是否存在等。
主要方法:
  • boolean add(E e) :向 Set 中添加一个元素,如果该元素已经存在,则不会添加并返回 false。
  • boolean contains(Object o) :判断 Set 中是否包含指定的元素。
  • boolean remove(Object o) :从 Set 中移除指定的元素。
  • int size() :返回 Set 中的元素个数。
  • boolean isEmpty() :判断 Set 是否为空。

3.1 HashSet

HashSet 是 Java 中 Set 接口的一个常见实现类,它基于哈希表实现。HashSet 不保证集合中元素的顺序,允许包含 null 元素,但不是线程安全的。

特点和优势
  • 不包含重复元素:与 Set 接口一致,HashSet 保证集合中不包含重复的元素,每个元素在 HashSet 中是唯一的。
  • 基于哈希表:HashSet 内部使用哈希表来存储元素,这使得查找、插入和删除操作具有很高的性能。
  • 无序性:HashSet 不保证元素的顺序,即元素存储的顺序和插入的顺序不一定相同。
  • 允许 null 元素:HashSet 允许包含一个 null 元素。
构造方法:
public HashSet() {map = new HashMap<>();
}public HashSet(Collection<? extends E> c) {map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));addAll(c);
}public HashSet(int initialCapacity, float loadFactor) {map = new HashMap<>(initialCapacity, loadFactor);
}public HashSet(int initialCapacity) {map = new HashMap<>(initialCapacity);
}//在LinkedHashSet的构造方法中调用
HashSet(int initialCapacity, float loadFactor, boolean dummy) {map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
主要方法
  • boolean add(E e) :向 HashSet 中添加一个元素,如果该元素已经存在,则不会添加并返回 false。
  • boolean contains(Object o) :判断 HashSet 中是否包含指定的元素。
  • boolean remove(Object o) :从 HashSet 中移除指定的元素。
  • int size() :返回 HashSet 中的元素个数。
  • boolean isEmpty() :判断 HashSet 是否为空。

示例代码:

import java.util.HashSet;
import java.util.Set;public class HashSetExample {public static void main(String[] args) {Set<String> fruitSet = new HashSet<>();fruitSet.add("Apple");fruitSet.add("Banana");fruitSet.add("Orange");System.out.println("Size of the set: " + fruitSet.size());fruitSet.remove("Banana");for (String fruit : fruitSet) {System.out.println(fruit);}}
}

3.2 TreeSet

TreeSet 是 Java 中 Set 接口的另一个常见实现类,它基于红黑树(Red-Black tree)实现。TreeSet 通过红黑树保证了集合元素的有序性,并且不允许包含 null 元素。
特点和优势:
  • 不包含重复元素:与 Set 接口一致,TreeSet 保证集合中不包含重复的元素,每个元素在 TreeSet 中是唯一的。
  • 有序性:TreeSet 通过红黑树实现,可以保证集合中的元素是有序的,通常是按照元素的自然顺序或者通过 Comparator 接口定义的比较规则进行排序。
  • 基于红黑树:红黑树是一种自平衡的二叉搜索树,能够保持高效的插入、删除和查找操作。
  • 不允许 null 元素:TreeSet 不允许包含 null 元素,否则会抛出 NullPointerException 异常。
构造方法:
public TreeSet() {this(new TreeMap<E,Object>());
}TreeSet(NavigableMap<E,Object> m) {this.m = m;
}public TreeSet(Comparator<? super E> comparator) {this(new TreeMap<>(comparator));
}public TreeSet(Collection<? extends E> c) {this();addAll(c);
}public TreeSet(SortedSet<E> s) {this(s.comparator());addAll(s);
}
主要方法:
  • boolean add(E e) :向 TreeSet 中添加一个元素,如果该元素已经存在,则不会添加并返回 false。
  • boolean contains(Object o) :判断 TreeSet 中是否包含指定的元素。
  • boolean remove(Object o) :从 TreeSet 中移除指定的元素。
  • int size() :返回 TreeSet 中的元素个数。
  • boolean isEmpty() :判断 TreeSet 是否为空。
示例代码:
import java.util.TreeSet;public class TreeSetExample {public static void main(String[] args) {// 创建一个TreeSet,元素自然排序(升序)TreeSet<Integer> numbers = new TreeSet<>();// 添加一些元素numbers.add(5);numbers.add(3);numbers.add(8);numbers.add(1);// 打印整个TreeSetSystem.out.println("TreeSet: " + numbers);// 查找是否存在某个元素System.out.println("Contains 6: " + numbers.contains(6));// 删除一个元素numbers.remove(3);System.out.println("TreeSet after removing 3: " + numbers);// 遍历TreeSetSystem.out.println("Traversing TreeSet:");for (int number : numbers) {System.out.println(number);}// 排序和检索操作System.out.println("First element: " + numbers.first());System.out.println("Last element: " + numbers.last());System.out.println("Element greater than 4: " + numbers.higher(4));System.out.println("Element lower than 4: " + numbers.lower(4));}
}

四、Queue

Queue 接口是 Java 集合框架中定义的一个接口,它代表了一种队列数据结构,遵循先进先出(FIFO)的原则。Queue 接口继承自 Collection 接口,提供了用于操作队列的方法。

主要方法:
  • 添加元素:
    • boolean add(E e) :将指定元素插入队列,如果队列已满则抛出异常。
    • boolean offer(E e) :将指定元素插入队列,如果队列已满则返回 false。
  • 获取并移除元素:
    • E remove() :获取并移除队列的头部元素,如果队列为空则抛出异常。
    • E poll() :获取并移除队列的头部元素,如果队列为空则返回 null。
  • 获取但不移除元素:
    • E element() :获取但不移除队列的头部元素,如果队列为空则抛出异常。
    • E peek() :获取但不移除队列的头部元素,如果队列为空则返回 null。
  • 其他方法:
    • int size() :返回队列中的元素个数。
    • boolean isEmpty() :判断队列是否为空。
常见实现类
  • LinkedList:实现了 Queue 接口,可以作为队列使用。
  • ArrayDeque:同样也实现了 Queue 接口,是一个基于数组实现的双端队列,可以作为队列使用。
  • PriorityQueue:优先级队列
应用场景
Queue 接口在 Java 中有许多实际的应用场景,特别是在需要进行异步处理、任务调度、消息传递等方面。以下是一些常见的 Queue 接口的应用场景:
  • 任务调度:在多线程编程中,可以使用队列来实现任务调度,将需要执行的任务按照一定的顺序或优先级放入队列中,然后由工作线程按照队列的顺序依次取出并执行这些任务。
  • 消息传递:在消息队列(Message Queue)系统中,消息被发送者放入队列,接收者从队列中获取消息并处理。这种方式可以实现解耦和异步通信,常见的消息队列如 RabbitMQ、Kafka 等都是基于队列的实现。
  • 生产者消费者模式:队列常常用于实现生产者消费者模式,生产者向队列中放入数据,消费者从队列中取出数据并进行处理,实现了生产和消费的解耦。
  • 线程池任务管理:线程池通常使用队列来存储待执行的任务,任务提交到线程池后会被放入队列中等待执行,线程池中的线程会从队列中取出任务并执行。
  • 网络爬虫:在网络爬虫程序中,可以使用队列来存储待访问的 URL,爬虫程序从队列中取出 URL 进行访问和解析,将新发现的 URL 放回队列中继续爬取。
  • 事件驱动编程:使用事件队列可以实现事件驱动编程模型,将事件按顺序放入队列中,然后由事件处理器逐个处理这些事件。

4.1 ArrayDeque

ArrayDeque 是一个基于数组实现的双端队列,为了满足可以同时在数组两端插入或删除元素的需求,数组必须是循环的,也就是说数组的任何一点都可以被看作是起点或者终点。

这是一个包含了 4 个元素的双端队列,和一个包含了 5 个元素的双端队列:

 head 指向队首的第一个有效的元素,tail 指向队尾第一个可以插入元素的空位,因为是循环数组,所以 head 不一定从是从 0 开始,tail 也不一定总是比 head 大。

4.2 PriorityQueue

PriorityQueue 是一种优先级队列,它的出队顺序与元素的优先级有关,执行 remove 或者 poll 方法,返回的总是优先级最高的元素。要想有优先级,元素就需要实现 Comparable 接口或者 Comparator 接口。

五、Map

Map 接口代表着一种映射关系,用来存储键值对。每个键都是唯一的,而值则可以重复。Map 接口提供了将键映射到值的功能,同时也允许通过键来检索对应的值。

特点:
  • 键值对映射:Map 中的数据以键值对的形式存储,每个键都与一个值相关联。
  • 键的唯一性:Map 中的键是唯一的,同一个键只能对应一个值。
  • 值的重复性:Map 中的值可以重复,不同的键可以映射到相同的值。
  • 键和值均可为 null:Map 中的键和值都可以为 null。
  • 实现类可以根据需求选择:Java 提供了多个实现 Map 接口的类,如 HashMap、TreeMap、LinkedHashMap、ConcurrentHashMap 等,每种实现类都有自己的特点和适用场景。
主要方法:
  • void clear() :清空 Map 中的所有键值对。
  • boolean containsKey(Object key) :判断 Map 中是否包含指定的键。
  • boolean containsValue(Object value) :判断 Map 中是否包含指定的值。
  • V get(Object key) :获取指定键对应的值。
  • boolean isEmpty() :判断 Map 是否为空。
  • SetkeySet() :返回包含所有键的 Set 集合。
  • V put(K key, V value) :向 Map 中添加键值对。
  • V remove(Object key) :移除指定键对应的键值对。
  • int size() :返回 Map 中键值对的数量。
  • Collectionvalues() :返回包含所有值的 Collection 集合。

5.1 HashMap (重点)

HashMap 是 Java 中最常用的 Map 接口的实现类之一,它基于哈希表实现,提供了快速的插入、删除和查找操作。

特点:
  • 基于哈希表:HashMap 内部通过哈希表来存储键值对,通过哈希算法可以快速定位到存储位置,实现了常数时间复杂度的插入、删除和查找操作。
  • 允许键和值为 null:HashMap 允许键和值都为 null,且可以有一个 null 键和多个 null 值。
  • 非线程安全:HashMap 是非线程安全的,如果需要在多线程环境下使用,可以考虑使用 ConcurrentHashMap。
  • 无序性:HashMap 不保证键值对的顺序,即插入顺序不会影响元素的遍历顺序。
  • 初始容量和加载因子:HashMap 可以指定初始容量和负载因子,加载因子表示哈希表在 rehashing(扩容)之前可以达到多满的程度,默认负载因子为 0.75。
  • 迭代器:HashMap 提供了迭代器(Iterator)来遍历键值对。
HashMap 类有多个构造方法,主要用于创建不同初始容量和加载因子的 HashMap 对象:
  • HashMap() :默认构造方法创建一个初始容量为 16,加载因子为 0.75 的空 HashMap。
  • HashMap(int initialCapacity) :创建一个指定初始容量,加载因子为 0.75 的空 HashMap。
  • HashMap(int initialCapacity, float loadFactor) :创建一个指定初始容量和加载因子的空 HashMap。
  • HashMap(Mapm) :使用指定 Map 中的键值对创建一个新的 HashMap。新 HashMap 的容量为原 Map 的两倍。
方法:
  • put(K key, V value) :将指定的键值对存储到 HashMap 中。
  • get(Object key) :获取指定键对应的值。
  • remove(Object key) :移除指定键对应的键值对。
  • containsKey(Object key) :判断是否包含指定的键。
  • size() :返回 HashMap 中键值对的数量。
  • keySet() :返回包含所有键的 Set 集合。
  • values() :返回包含所有值的 Collection 集合。​​
原理概述:
  • HashMap 底层通过数组、链表、红黑树组合实现。数组被称为“桶”(buckets),每个桶存储一个链表或者一个红黑树,桶位置的节点为链表或红黑树的头结点。
  • HashMap 根据 key 的 hashCode 值来确定其存储位置,通过 hashCode 来快速定位到对应的桶。
    • hash :h = key.hashCode()) ^ (h >>> 16) hashcode与hashcode右移16位做异或运算,为了使hashcode的高位也参加运算,使key充分散列
    • i = (n - 1) & hash 通过hash值计算出桶的位置
  • hashCode 和 equals 方法:
    • 在 HashMap 中,key 的 hashCode 用于确定其在数组中的索引位置。
    • 如果两个 key 的 hashCode 相同,HashMap 会使用 equals 方法来进一步判断它们是否相等。
  • 解决哈希冲突:
    • 当不同的 key 计算出相同的 hashCode 值时,就会发生哈希冲突。
    • HashMap 使用链表或红黑树来存储具有相同 hashCode 的 key-value 对,以解决哈希冲突。
    • 当链表长度过长(默认超过8个节点),链表会转换为红黑树,以提高检索效率。
  • 扩容与负载因子:
    • 当 HashMap 中的元素个数超过负载因子(默认为 0.75 * 容量)时,HashMap 会进行扩容操作。
    • 扩容会创建一个新的更大的数组(2倍扩容:newCap = oldCap << 1),并将原数组中的元素重新分配到新数组中,以减少哈希碰撞。
  • 迭代顺序:
    • HashMap 的遍历顺序并不是按照插入顺序或者自然顺序,而是根据 key 的 hashCode 来确定顺序。
    • 因此,HashMap 中的元素遍历顺序是不确定的,不同的运行环境可能会有不同的遍历顺序。
  • 线程安全性:
    • HashMap 在多线程环境下不是线程安全的,如果需要在多线程环境中使用,可以考虑使用 ConcurrentHashMap。

5.2 ConcurrentHashMap(重点)

ConcurrentHashMap是J.U.C(java.util.concurrent包)的重要成员,它是HashMap的一个线程安全的、支持高并发的版本。

Map 接口的另一个实现类 Hashtable 虽然是线程安全的,但是执行效率很低。

JDK 1.7及之前版本: 采用分段锁(Segment):
  • 哈希表被分为多个段,每个段独立加锁。
  • 每个段是一个小的哈希表,有自己的锁。
  • 支持多个更新操作并行,只要它们发生在不同的段上。
JDK 1.8及之后版本: 废弃分段锁,采用 CAS 结合 synchronized 锁细化的桶来实现线程安全:
  • 哈希表的每个桶变得可以独立加锁。
  • 链表转红黑树 :当桶中的元素数量达到一定阈值时,链表结构将转变为红黑树,以减少搜索时间。
  • 锁分离技术: 读操作几乎不需要锁,写操作锁定的范围大大减少。结合 CAS 操作,提高了并发性能。
ConcurrentHashMap不仅仅是线程安全的,它还通过一系列精妙的设计实现了与效率的平衡:
  • 不允许null值:与HashMap相比,ConcurrentHashMap不允许键或值为null,这样设计可以避免并发情况下的歧义。
  • 高效的迭代器:ConcurrentHashMap的迭代器具有弱一致性,这意味着迭代器创建后的修改不一定能反映在它上面,但它们不会抛出ConcurrentModificationException异常。
  • 无锁读取:ConcurrentHashMap的获取操作通常不需要锁定或者只需要很小的同步开销(CAS操作)。
构造方法:
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable {//......public ConcurrentHashMap() {}public ConcurrentHashMap(int initialCapacity) {if (initialCapacity < 0)throw new IllegalArgumentException();int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?MAXIMUM_CAPACITY :tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));this.sizeCtl = cap;}public ConcurrentHashMap(int initialCapacity, float loadFactor) {this(initialCapacity, loadFactor, 1);}public ConcurrentHashMap(int initialCapacity,float loadFactor, int concurrencyLevel) {if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)throw new IllegalArgumentException();if (initialCapacity < concurrencyLevel)   // Use at least as many binsinitialCapacity = concurrencyLevel;   // as estimated threadslong size = (long)(1.0 + (long)initialCapacity / loadFactor);int cap = (size >= (long)MAXIMUM_CAPACITY) ?MAXIMUM_CAPACITY : tableSizeFor((int)size);this.sizeCtl = cap;}public ConcurrentHashMap(Map<? extends K, ? extends V> m) {this.sizeCtl = DEFAULT_CAPACITY;putAll(m);}
}

5.3 LinkedHashMap

LinkedHashMap​是Java中的一个类,它继承自HashMap​,并且保留了元素插入的顺序。

大多数情况下,只要不涉及线程安全问题,Map基本都可以使用HashMap,不过HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序。HashMap的这一缺点往往会带来困扰,因为有些场景,我们期待一个有序的Map。

于是 LinkedHashMap 就闪亮登场了。LinkedHashMap 是 HashMap 的子类,内部使用链表来记录插入/访问元素的顺序。

LinkedHashMap 可以看作是 HashMap + LinkedList 的合体,它使用了 哈希表来存储数据,又用了双向链表来维持顺序。

特点:
  • 保持插入顺序:LinkedHashMap​会记住元素的插入顺序,并且迭代时会按照插入顺序返回元素。
  • 内部采用双向链表维护顺序:在LinkedHashMap​内部,元素以双向链表连接起来,这样可以保证元素的有序性。
构造方法:
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {//......//创建一个空的LinkedHashMap​,默认初始容量为16,负载因子为0.75public LinkedHashMap() {super();accessOrder = false;}//创建一个指定初始容量的LinkedHashMappublic LinkedHashMap(int initialCapacity) {super(initialCapacity);accessOrder = false;}//创建一个指定初始容量和负载因子的LinkedHashMappublic LinkedHashMap(int initialCapacity, float loadFactor) {super(initialCapacity, loadFactor);accessOrder = false;}public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {super(initialCapacity, loadFactor);this.accessOrder = accessOrder;}//创建一个包含指定映射中的所有映射关系的LinkedHashMappublic LinkedHashMap(Map<? extends K, ? extends V> m) {super();accessOrder = false;putMapEntries(m, false);}//......
}
主要方法:
  • put(K key, V value): 将键值对添加到LinkedHashMap​中。
  • get(Object key): 获取指定键对应的值。
  • remove(Object key): 移除指定键对应的映射关系。
  • clear(): 清空LinkedHashMap​中的所有映射关系。
  • keySet(): 返回包含所有键的Set视图。
  • entrySet(): 返回包含所有映射关系的Set视图。
示例代码:
// 创建一个LinkedHashMap实例
LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<>();// 向LinkedHashMap中添加元素
linkedHashMap.put("A", 1);
linkedHashMap.put("B", 2);
linkedHashMap.put("C", 3);// 遍历LinkedHashMap并打印键值对(按插入顺序)
for (Map.Entry<String, Integer> entry : linkedHashMap.entrySet()) {System.out.println(entry.getKey() + ": " + entry.getValue());
}// 输出结果将会按照插入顺序:
// A: 1
// B: 2
// C: 3

5.4 TreeMap

TreeMap 类是基于红黑树数据结构实现的有序映射(键值对)集合。它继承自 AbstractMap 类并实现了 NavigableMap 接口。TreeMap 通过红黑树实现了按键的自然顺序或自定义顺序排序,并且提供了一些额外的功能。

特点:
  • 有序性: TreeMap 中的键值对是根据键的自然顺序或者通过 Comparator 进行排序的。这使得 TreeMap 能够按照键的顺序进行遍历和范围查询。
  • 基于红黑树: TreeMap 内部使用红黑树作为数据结构来存储键值对,红黑树是一种自平衡的二叉搜索树,能够保持高效的插入、删除和查找操作。
  • 支持子视图: TreeMap 提供了多种方法来获取子视图,如 subMap()​, headMap()​, tailMap()​,可以方便地对 TreeMap 进行范围操作。
  • 性能: TreeMap 中的基本操作(插入、删除、查找)的时间复杂度为 O(log n),其中 n 为 TreeMap 中的元素个数。由于红黑树的自平衡性质,TreeMap 在大部分情况下能够保持较好的性能。
构造方法:
public class TreeMap<K,V> extends AbstractMap<K,V>implements NavigableMap<K,V>, Cloneable, java.io.Serializable {//......//创建一个空的TreeMap​,按照键的自然顺序进行排序public TreeMap() {comparator = null;}//创建一个空的TreeMap​,按照指定比较器进行排序public TreeMap(Comparator<? super K> comparator) {this.comparator = comparator;}//创建一个TreeMap​,其中包含指定映射中的所有映射关系public TreeMap(Map<? extends K, ? extends V> m) {comparator = null;putAll(m);}public TreeMap(SortedMap<K, ? extends V> m) {comparator = m.comparator();try {buildFromSorted(m.size(), m.entrySet().iterator(), null, null);} catch (java.io.IOException cannotHappen) {} catch (ClassNotFoundException cannotHappen) {}}//......
}
主要方法:
  • put(key, value)​:向 TreeMap 中插入键值对。
  • get(key)​:获取指定键对应的值。
  • remove(key)​:移除指定键及其对应的值。
  • containsKey(key)​:判断 TreeMap 是否包含指定的键。
  • size()​:返回 TreeMap 的大小(键值对数量)。
  • keySet()​:返回包含所有键的 Set 集合。
  • values()​:返回包含所有值的 Collection 集合。
  • entrySet()​:返回包含所有键值对的 Set 集合。
代码示例:
import java.util.TreeMap;public class TreeMapExample {public static void main(String[] args) {// 创建一个 TreeMap 实例TreeMap<String, Integer> treeMap = new TreeMap<>();// 向 TreeMap 中插入键值对treeMap.put("apple", 10);treeMap.put("banana", 20);treeMap.put("orange", 15);// 获取指定键对应的值System.out.println("The value of apple: " + treeMap.get("apple"));// 移除指定键及其对应的值treeMap.remove("banana");// 遍历 TreeMap 中的键值对for (String key : treeMap.keySet()) {System.out.println(key + ": " + treeMap.get(key));}// 创建一个空的TreeMap,按照指定比较器进行排序Comparator<String> customComparator = new CustomComparator(); // 假设CustomComparator是自定义的比较器TreeMap<String, Integer> treeMap2 = new TreeMap<>(customComparator);}
}

六、Iterator 迭代器

迭代器(Iterator)是 Java 集合框架中的一种机制,是一种用于遍历集合(如列表、集合和映射等)的接口。

它提供了一种统一的方式来访问集合中的元素,而不需要了解底层集合的具体实现细节。

由于每一个容器都有取出元素的功能。这些功能定义都一样,只不过实现的具体方式不同(因为每一个容器的数据结构不一样)所以对共性的取出功能进行了抽取,从而出现了 Iterator 接口。而每一个容器都在其内部对该接口进行了内部类的实现,也就是将取出方式的细节进行封装

如何获取迭代器?Collection 接口中定义了获取集合类迭代器的方法(iterator()),所以所有的 Collection 体系集合都可以获取自身的迭代器。

Iterator 是 Java 迭代器最简单的实现,ListIterator 继承扩展了 Iterator 接口:

迭代器接口定义了几个方法,最常用的是以下三个:
  • next() - 返回迭代器的下一个元素,并将迭代器的指针移到下一个位置。
  • hasNext() - 用于判断集合中是否还有下一个元素可以访问。
  • remove() - 从集合中删除迭代器最后访问的元素(可选操作)。
ListIterator 是 List专属的迭代器,对 Iterator 进行了扩展:
  • add(E e) 将指定的元素插入列表(可选操作)。该元素直接插入到 next 返回的下一个元素的前面(如果有)
  • void set(E o) 用指定元素替换 next 或 previous 返回的最后一个元素
  • hasPrevious() 逆向遍历列表,列表迭代器有多个元素,则返回 true。
  • previous() 返回列表中的前一个元素。

Iterator在迭代时,只能对元素进行获取(next())和删除(remove())的操作。

对于 Iterator 的子接口 ListIterator 在迭代list 集合时,还可以对元素进行添加 add(obj),修改set(obj) 操作,甚至还能倒序遍历。

6.1 Iterable

Collection 的父接口。实现了 Iterable 的类就是可迭代的,并且支持增强for循环。

Collection 接口继承了 Iterable ,所以 Collection 体系都具备获取自身迭代器的方法,只不过每个子类集合都进行了重写(因为数据结构不同)。

6.2 ArrayList#iterator()

ArrayList 实现的 Iterator ,源码如下:

public class ArrayList<E> extends AbstractList<E> {//......public Iterator<E> iterator() {return new Itr();}/*** An optimized version of AbstractList.Itr*/private class Itr implements Iterator<E> {int cursor;       // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;Itr() {}public boolean hasNext() {return cursor != size;}@SuppressWarnings("unchecked")public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];}public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}@Override@SuppressWarnings("unchecked")public void forEachRemaining(Consumer<? super E> consumer) {Objects.requireNonNull(consumer);final int size = ArrayList.this.size;int i = cursor;if (i >= size) {return;}final Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length) {throw new ConcurrentModificationException();}while (i != size && modCount == expectedModCount) {consumer.accept((E) elementData[i++]);}// update once at end of iteration to reduce heap write trafficcursor = i;lastRet = i - 1;checkForComodification();}final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}//......
}

ArrayList 实现的 ListIterator ,源码如下:

public class ArrayList<E> extends AbstractList<E> {//......public ListIterator<E> listIterator() {return new ListItr(0);}private class ListItr extends Itr implements ListIterator<E> {ListItr(int index) {super();cursor = index;}public boolean hasPrevious() {return cursor != 0;}public int nextIndex() {return cursor;}public int previousIndex() {return cursor - 1;}@SuppressWarnings("unchecked")public E previous() {checkForComodification();int i = cursor - 1;if (i < 0)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i;return (E) elementData[lastRet = i];}public void set(E e) {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {ArrayList.this.set(lastRet, e);} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}public void add(E e) {checkForComodification();try {int i = cursor;ArrayList.this.add(i, e);cursor = i + 1;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}}//......
}

可以看到 ArrayList 内部定义类 Iterator 的实现类 Itr ,以及 ListIterator 的实现类 ListItr。

6.3 迭代器遍历

1)while循环

public static void main(String[] args) {ArrayList list = new ArrayList();list.add("计算机网络");list.add("现代操作系统");list.add("java编程思想");list.add("java核心技术");list.add("java语言程序设计");Iterator it = list.iterator();while (it.hasNext()) {String next = (String) it.next();System.out.println(next);}
}

2)for循环

public static void main(String[] args) {ArrayList list = new ArrayList();// 增加:add() 将指定对象存储到容器中list.add("计算机网络");list.add("现代操作系统");list.add("java编程思想");list.add("java核心技术");list.add("java语言程序设计");for (Iterator it = list.iterator(); it.hasNext();) {//迭代器的next方法返回值类型是Object,所以要记得类型转换。String next = (String) it.next();System.out.println(next);}
}

注意:

  • 如果迭代器的指针已经指向了集合的末尾,那么如果再调用next()会返回NoSuchElementException异常
  • 如果调用remove之前没有调用next是不合法的,会抛出IllegalStateException
  • 在用迭代器对集合进行迭代过程中,不允许出现迭代器以外的对元素的操作,因为这样会产生安全隐患,java会抛出异常并发修改异常(ConcurrentModificationException),普通迭代器 Iterator 只支持在迭代过程中的 remove() 删除操作。如果是List集合,想要在迭代中操作元素可以使用List集合的特有迭代器ListIterator,该迭代器支持在迭代过程中,添加元素和修改元素。

使用ListIterator 遍历List:

public static void main(String[] args) {ArrayList list = new ArrayList();list.add("计算机网络");list.add("现代操作系统");list.add("java编程思想");list.add("java核心技术");list.add("java语言程序设计");// 获取List专属的迭代器ListIterator lit = list.listIterator();//正序遍历while (lit.hasNext()) {String next = (String) lit.next();System.out.println(next);}System.out.println("***************");//倒序遍历while (lit.hasPrevious()) {String next = (String)lit.previous();System.out.println(next);}
}

七、集合工具类

7.1 Collections

Collections 是 JDK 提供的一个工具类,位于 java.util 包下,提供了一系列的静态方法,方便我们对集合进行各种骚操作,算是集合框架的一个大管家。

常用方法如下。

7.1.1 排序操作

  • reverse(List list)​:反转顺序
  • shuffle(List list)​:洗牌,将顺序打乱
  • sort(List list)​:自然升序
  • sort(List list, Comparator c)​:按照自定义的比较器排序
  • swap(List list, int i, int j)​:将 i 和 j 位置的元素交换位置
List<String> list = new ArrayList<>();
list.add("沉默王二");
list.add("沉默王三");
list.add("沉默王四");
list.add("沉默王五");
list.add("沉默王六");System.out.println("原始顺序:" + list);// 反转
Collections.reverse(list);
System.out.println("反转后:" + list);// 洗牌
Collections.shuffle(list);
System.out.println("洗牌后:" + list);// 自然升序
Collections.sort(list);
System.out.println("自然升序后:" + list);// 交换
Collections.swap(list, 2,4);
System.out.println("交换后:" + list);//结果打印
原始顺序:[沉默王二, 沉默王三, 沉默王四, 沉默王五, 沉默王六]
反转后:[沉默王六, 沉默王五, 沉默王四, 沉默王三, 沉默王二]
洗牌后:[沉默王五, 沉默王二, 沉默王六, 沉默王三, 沉默王四]
自然升序后:[沉默王三, 沉默王二, 沉默王五, 沉默王六, 沉默王四]
交换后:[沉默王三, 沉默王二, 沉默王四, 沉默王六, 沉默王五]

7.1.2 查找替换

  • binarySearch(List list, Object key)​:二分查找法,前提是 List 已经排序过了
  • max(Collection coll)​:返回最大元素
  • max(Collection coll, Comparator comp)​:根据自定义比较器,返回最大元素
  • min(Collection coll)​:返回最小元素
  • min(Collection coll, Comparator comp)​:根据自定义比较器,返回最小元素
  • fill(List list, Object obj)​:使用指定对象填充
  • frequency(Collection c, Object o)​:返回指定对象出现的次数
System.out.println("最大元素:" + Collections.max(list));
System.out.println("最小元素:" + Collections.min(list));
System.out.println("出现的次数:" + Collections.frequency(list, "沉默王二"));// 没有排序直接调用二分查找,结果是不确定的
System.out.println("排序前的二分查找结果:" + Collections.binarySearch(list, "沉默王二"));
Collections.sort(list);
// 排序后,查找结果和预期一致
System.out.println("排序后的二分查找结果:" + Collections.binarySearch(list, "沉默王二"));Collections.fill(list, "沉默王八");
System.out.println("填充后的结果:" + list);//结果打印
原始顺序:[沉默王二, 沉默王三, 沉默王四, 沉默王五, 沉默王六]
最大元素:沉默王四
最小元素:沉默王三
出现的次数:1
排序前的二分查找结果:0
排序后的二分查找结果:1
填充后的结果:[沉默王八, 沉默王八, 沉默王八, 沉默王八, 沉默王八]

7.1.3 checkedxxx 检查集合

返回类型检查的集合,在对类型进行set 或者add的时候会做类型检查。

public static void main(String[] args) {ArrayList list = Lists.newArrayList();list.add(new Player("香菜"));//  返回的safeList 在add时会进行类型检查List safeList = Collections.checkedList(list, Player.class);//此时会对类型进行检查,不是Player类型,抛出异常 java.lang.ClassCastException:safeList.add("xxx");
}

7.1.4 emptyxxx 返回空的集合

用这个方法的好处在于:
  • 不用处理返回null的问题。
  • 不用新生成空的list,避免占用内存,因为返回的空list,整个应用共同用一个(statics final修饰)。

7.1.5 synchronizedxxx 同步集合

ArrayList<Player> list = Lists.newArrayList();
//  TODO;-----
List<Player> synList = Collections.synchronizedList(list);

SynchronizedList 为 Collections 的内部类,源码如下:

static class SynchronizedList<E> extends SynchronizedCollection<E>implements List<E> {private static final long serialVersionUID = -7754090372962971524L;final List<E> list;SynchronizedList(List<E> list) {super(list);this.list = list;}SynchronizedList(List<E> list, Object mutex) {super(list, mutex);this.list = list;}public boolean equals(Object o) {if (this == o)return true;synchronized (mutex) {return list.equals(o);}}public int hashCode() {synchronized (mutex) {return list.hashCode();}}public E get(int index) {synchronized (mutex) {return list.get(index);}}public E set(int index, E element) {synchronized (mutex) {return list.set(index, element);}}public void add(int index, E element) {synchronized (mutex) {list.add(index, element);}}public E remove(int index) {synchronized (mutex) {return list.remove(index);}}//......
}

可以看到,实际相当于对集合进行了二次包装,在内部加了一把锁。

7.1.6 unmodifiableXxx 不可变集合

传入的集合返回后不可以改变。

ArrayList<Player> list = Lists.newArrayList();
//  TODO;-----
List<Player> synList = Collections.unmodifiableList(list);

UnmodifiableList 为 Collections 的内部类,源码如下:

static class UnmodifiableList<E> extends UnmodifiableCollection<E>implements List<E> {private static final long serialVersionUID = -283967356065247728L;final List<? extends E> list;UnmodifiableList(List<? extends E> list) {super(list);this.list = list;}public E get(int index) {return list.get(index);}public E set(int index, E element) {throw new UnsupportedOperationException();}public void add(int index, E element) {throw new UnsupportedOperationException();}public E remove(int index) {throw new UnsupportedOperationException();}public int indexOf(Object o)            {return list.indexOf(o);}public int lastIndexOf(Object o)        {return list.lastIndexOf(o);}public boolean addAll(int index, Collection<? extends E> c) {throw new UnsupportedOperationException();}@Overridepublic void replaceAll(UnaryOperator<E> operator) {throw new UnsupportedOperationException();}@Overridepublic void sort(Comparator<? super E> c) {throw new UnsupportedOperationException();}//......
}

可以看到,包装类屏蔽了集合的方法,抛出了异常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/18164.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k8s集群搭建参考(by lqw)

文章目录 声明配置yum源安装docker安装 kubeadm&#xff0c;kubelet 和 kubectl部署主节点其他节点加入集群安装网络插件 声明 由于看了几个k8s的教程&#xff0c;都存在各种问题&#xff0c;自己搭建的时候&#xff0c;踩了不少坑&#xff0c;最后还是靠百度csdnchatGPT才搭建…

MySQL 插入替换语句(replace into statement)

我们日常使用 insert into 语句向表中插入数据时&#xff0c;一定遇到过主键或唯一索引冲突的情况&#xff0c;MySQL的反应是报错并停止执行后续的语句&#xff0c;而replace into语句可以实现强制插入。 文章目录 一、replace into 语句简介1.1 基本用法1.2 使用set语句 二、注…

日语发音的节拍

短音 每个假名&#xff08;包括清音、浊音、半浊音&#xff09;都占 1 拍。 长音 长音占 2 拍&#xff0c;发音时间比短音长 不同母音的长音形式不同&#xff08;あ段あ&#xff0c;い段い&#xff0c;う段う&#xff0c;え段い/え&#xff0c;お段う/お&#xff09; 促音 …

[AI]从零开始的llama.cpp部署与DeepSeek格式转换、量化、运行教程

一、前言 在上一次的DeepSeek的部署教程中&#xff0c;我们使用Ollama与LM Studio很轻松的部署了DeepSeek并且也完成了相关API的调用&#xff0c;如果还有不会的小伙伴请看下面的教程&#xff1a; DeepSeek本地部署&#xff1a;[AI]从零开始的DeepSeek本地部署及本地API调用教…

基于SSM+uniapp的数学辅导小程序+LW示例参考

1.项目介绍 系统角色&#xff1a;管理员、普通用户功能模块&#xff1a;用户管理、学习中心、知识分类管理、学习周报管理、口算练习管理、试题管理、考试管理、错题本等技术选型&#xff1a;SSM&#xff0c;Vue&#xff08;后端管理web&#xff09;&#xff0c;uniapp等测试环…

解决DeepSeek服务器繁忙问题

目录 解决DeepSeek服务器繁忙问题 一、用户端即时优化方案 二、高级技术方案 三、替代方案与平替工具&#xff08;最推荐简单好用&#xff09; 四、系统层建议与官方动态 用加速器本地部署DeepSeek 使用加速器本地部署DeepSeek的完整指南 一、核心原理与工具选择 二、…

B+Tree在mysql中的使用

BTree的结构 BTree是B-Tree的变种&#xff0c;实际结构如图 绿色框框起来的部分&#xff0c;是索引部分&#xff0c;仅仅起到索引数据的作用&#xff0c;不存储数据。红色框框起来的部分&#xff0c;是数据存储部分&#xff0c;在其叶子节点中要存储具体的数据 BTree的特点 所有…

vue学习10

1.GPT和Copilot Copilot Tab接受 删除键&#xff0c;不接受 ctrlenter更多方案 更适合的是修改方向 const submitForm async () > {//等待校验结果await formRef.value.validate()//提交修改await userUpdateInfoService(form.value)//通知user模块&#xff0c;进行数据更…

我的新书《青少年Python趣学编程(微课视频版)》出版了!

&#x1f389; 激动人心的时刻来临啦&#xff01; &#x1f389; 小伙伴们久等了&#xff0c;我的第一本新书 《青少年Python趣学编程&#xff08;微课视频版&#xff09;》 正式出版啦&#xff01; &#x1f4da;✨ 在这个AI时代&#xff0c;市面上的Python书籍常常过于枯燥&…

总结:如何在SpringBoot中使用https协议以及自签证书?

总结&#xff1a;如何在SpringBoot中使用https协议以及自签证书&#xff1f; 前提一&#xff1a;什么是http协议&#xff1f;前提二&#xff1a;什么是https协议&#xff1f;一生成自签证书二 将证书转换为PKCS12格式三 配置SpringBoot&#xff08;1&#xff09;修改配置文件&a…

JAVA毕业设计212—基于Java+Springboot+vue3的校园运动场馆预约管理系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootvue3的校园运动场馆预约管理系统(源代码数据库)212 一、系统介绍 本项目前后端分离(可以改为ssm版本)&#xff0c;分为用户、管理员两种角色 1、用户&#xff…

在nodejs中使用RabbitMQ(六)sharding消息分片

RabbitMQ 的分片插件&#xff08;rabbitmq_sharding&#xff09;允许将消息分布到多个队列中&#xff0c;这在消息量很大或处理速度要求高的情况下非常有用。分片功能通过将消息拆分到多个队列中来平衡负载&#xff0c;从而提升消息处理的吞吐量和可靠性。它能够在多个队列之间…

数据结构 二叉树

一、⼆叉树的定义 ⼆叉树是⼀种特殊的树型结构&#xff0c;它的特点是每个结点⾄多只有2棵⼦树&#xff08;即⼆叉树中不存在度⼤于2的结点&#xff09;&#xff0c;并且⼆叉树的⼦树有左右之分&#xff0c;其次序不能任意颠倒。 ⼆叉的意思是这种树的每⼀个结点最多只有两个孩…

本地部署DeepSeek集成VSCode创建自己的AI助手

文章目录 安装Ollama和CodeGPT安装Ollama安装CodeGPT 下载并配置DeepSeek模型下载聊天模型&#xff08;deepseek-r1:1.5b&#xff09;下载自动补全模型&#xff08;deepseek-coder:1.3b&#xff09; 使用DeepSeek进行编程辅助配置CodeGPT使用DeepSeek模型开始使用AI助手 ✍️相…

【NLP】循环神经网络RNN

目录 一、词嵌入层 二、循环网络层 2.1 RNN网络原理 2.2 Pytorch RNN API 自然语言处理&#xff08;Nature language Processing&#xff0c;NLP&#xff09;研究的主要是通过计算机算法来理解自然语言。对于自然语言来说&#xff0c;处理的数据主要就是人类的语言&#xf…

利用蓝耘智算平台深度搭建deepseek R1模型,进行深度机器学习

大佬请阅读 前言关于DeepSeek 的显著优点卓越的性能表现低廉的训练成本广泛的应用场景开放的开源策略 DeepSeek 与其他 AI 对比什么是蓝耘智算平台为什么使用蓝耘智算平台搭建我们的deepseek如何使用蓝耘 GPU 智算云平台搭建我们的R1模型并成功进行调用测试11. AVL树节点结构2.…

spring6(完结)

像是八大模式这种&#xff0c;放在后面八股文中再重点了解&#xff0c;对于源码部分也是后面会一起手敲。 个人觉得spring的重点在于注解开发&#xff0c;省去了很多耦合的问题&#xff0c;像是各种事务的管理&#xff0c;和bean类的管理都可以给spring容器管理&#xff0c;注入…

H5自适应响应式代理记账与财政咨询服务类PbootCMS网站模板 – HTML5财务会计类网站源码下载

(H5自适应)响应式代理记账财政咨询服务类pbootcms网站模板 html5财务会计类网站源码下载 为了提升系统安全&#xff0c;请将后台文件admin.php的文件名修改一下。修改之后&#xff0c;后台登录地址就是&#xff1a;您的域名/您修改的文件名.php 模板特点&#xff1a; 1&#x…

Java 大视界 -- 量子计算时代 Java 大数据的潜在变革与应对策略(88)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

[css] 黑白主题切换

link动态引入 类名切换 css滤镜 var 类名切换 v-bind css预处理器mixin类名切换 【前端知识分享】CSS主题切换方案