(二十一)Java集合框架源码深度解析
一、集合框架概述
Java集合框架(Java Collections Framework, JCF)是Java语言中用于存储和操作数据集合的一套标准架构。它提供了一组接口、实现类和算法,使开发者能够高效地处理各种数据结构。
1.1 集合框架的历史演变
在Java 1.2之前,Java只有几种简单的集合类:
-
Vector
-
Hashtable
-
数组
-
Properties
这些早期集合类存在诸多问题:
-
命名不规范
-
方法命名不一致
-
缺乏统一的接口
-
性能不佳
Java 1.2引入了全新的集合框架,主要设计者为Joshua Bloch。这个新框架具有以下特点:
-
统一的接口层次结构
-
高性能实现
-
可扩展性
-
类型安全(通过泛型)
1.2 集合框架的核心接口
Java集合框架的核心接口构成了一个层次结构:
Iterable └── Collection├── List├── Set│ └── SortedSet└── Queue└── Deque
此外还有独立的Map接口及其子接口SortedMap。
二、Collection接口解析
Collection接口是集合框架的根接口之一,定义了所有集合类共有的基本操作。
2.1 核心方法分析
java
public interface Collection<E> extends Iterable<E> {// 基本操作int size();boolean isEmpty();boolean contains(Object o);Iterator<E> iterator();Object[] toArray();<T> T[] toArray(T[] a);// 修改操作boolean add(E e);boolean remove(Object o);// 批量操作boolean containsAll(Collection<?> c);boolean addAll(Collection<? extends E> c);boolean removeAll(Collection<?> c);boolean retainAll(Collection<?> c);void clear();// 比较和哈希boolean equals(Object o);int hashCode();// JDK 8新增的默认方法default boolean removeIf(Predicate<? super E> filter) {Objects.requireNonNull(filter);boolean removed = false;final Iterator<E> each = iterator();while (each.hasNext()) {if (filter.test(each.next())) {each.remove();removed = true;}}return removed;}// 其他默认方法...
}
2.2 设计模式应用
Collection接口体现了多种设计模式:
-
迭代器模式:通过iterator()方法提供遍历集合的标准方式
-
模板方法模式:默认方法removeIf()提供了基于条件删除的通用实现
-
策略模式:通过传递Predicate实现不同的删除策略
三、List接口及其实现
List代表有序集合(序列),允许重复元素和null值。
3.1 ArrayList源码分析
ArrayList是基于动态数组的实现,是List最常用的实现类。
3.1.1 核心字段
java
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {// 默认初始容量private static final int DEFAULT_CAPACITY = 10;// 空数组实例,用于空实例private static final Object[] EMPTY_ELEMENTDATA = {};// 默认大小的空数组实例private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};// 存储ArrayList元素的数组缓冲区transient Object[] elementData;// ArrayList的大小(包含的元素数量)private int size;// 修改计数器,用于快速失败机制protected transient int modCount = 0;
}
3.1.2 扩容机制
ArrayList的核心扩容方法grow():
java
private void grow(int minCapacity) {// 溢出安全的代码int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5倍if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// 最小容量通常接近size,所以这是扩容操作elementData = Arrays.copyOf(elementData, newCapacity);
}
扩容过程:
-
计算新容量为旧容量的1.5倍
-
检查是否满足最小容量要求
-
检查是否超过最大数组大小限制
-
使用Arrays.copyOf()创建新数组并复制元素
3.1.3 添加元素
java
public boolean add(E e) {modCount++;add(e, elementData, size);return true;
}private void add(E e, Object[] elementData, int s) {if (s == elementData.length)elementData = grow();elementData[s] = e;size = s + 1;
}
3.1.4 删除元素
java
public E remove(int index) {Objects.checkIndex(index, size);final Object[] es = elementData;@SuppressWarnings("unchecked") E oldValue = (E) es[index];fastRemove(es, index);return oldValue;
}private void fastRemove(Object[] es, int i) {modCount++;final int newSize;if ((newSize = size - 1) > i)System.arraycopy(es, i + 1, es, i, newSize - i);es[size = newSize] = null;
}
3.2 LinkedList源码分析
LinkedList是基于双向链表的实现,同时实现了List和Deque接口。
3.2.1 节点结构
java
private static class Node<E> {E item;Node<E> next;Node<E> prev;Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}
}
3.2.2 核心字段
java
transient int size = 0;
transient Node<E> first; // 头节点
transient Node<E> last; // 尾节点
3.2.3 添加元素
java
public boolean add(E e) {linkLast(e);return true;
}void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;modCount++;
}
3.2.4 删除元素
java
public E remove(int index) {checkElementIndex(index);return unlink(node(index));
}E unlink(Node<E> x) {final E element = x.item;final Node<E> next = x.next;final Node<E> prev = x.prev;if (prev == null) {first = next;} else {prev.next = next;x.prev = null;}if (next == null) {last = prev;} else {next.prev = prev;x.next = null;}x.item = null;size--;modCount++;return element;
}
3.3 Vector与ArrayList对比
Vector是线程安全的ArrayList,但性能较差。主要区别:
-
同步机制:Vector所有方法都是同步的
-
扩容策略:Vector默认增长一倍,ArrayList增长50%
-
遗留类:Vector是Java 1.0的遗留类
四、Set接口及其实现
Set是不包含重复元素的集合,最多包含一个null元素。
4.1 HashSet源码分析
HashSet是基于HashMap的实现,使用对象的hashCode()和equals()方法来确保唯一性。
4.1.1 核心字段
java
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
4.1.2 构造方法
java
public HashSet() {map = new HashMap<>();
}public HashSet(int initialCapacity) {map = new HashMap<>(initialCapacity);
}
4.1.3 添加元素
java
public boolean add(E e) {return map.put(e, PRESENT)==null;
}
4.2 LinkedHashSet源码分析
LinkedHashSet继承自HashSet,但内部使用LinkedHashMap维护插入顺序。
4.2.1 构造方法
java
public LinkedHashSet(int initialCapacity) {super(initialCapacity, .75f, true);
}// HashSet中的特殊构造方法
HashSet(int initialCapacity, float loadFactor, boolean dummy) {map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
4.3 TreeSet源码分析
TreeSet是基于TreeMap的NavigableSet实现,元素按照自然顺序或Comparator排序。
4.3.1 核心字段
java
private transient NavigableMap<E,Object> m;
private static final Object PRESENT = new Object();
4.3.2 构造方法
java
public TreeSet() {this(new TreeMap<E,Object>());
}public TreeSet(Comparator<? super E> comparator) {this(new TreeMap<>(comparator));
}
五、Map接口及其实现
Map是键值对的集合,每个键最多映射到一个值。
5.1 HashMap源码分析
HashMap是基于哈希表的Map实现,允许null键和null值。
5.1.1 核心字段
java
// 默认初始容量 - 必须是2的幂
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 16// 最大容量
static final int MAXIMUM_CAPACITY = 1 << 30;// 默认负载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;// 链表转红黑树的阈值
static final int TREEIFY_THRESHOLD = 8;// 红黑树转链表的阈值
static final int UNTREEIFY_THRESHOLD = 6;// 最小树化容量
static final int MIN_TREEIFY_CAPACITY = 64;// 哈希表
transient Node<K,V>[] table;// 键值对集合
transient Set<Map.Entry<K,V>> entrySet;// 元素数量
transient int size;// 修改计数器
transient int modCount;// 扩容阈值 (capacity * load factor)
int threshold;// 负载因子
final float loadFactor;
5.1.2 节点结构
java
static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;V value;Node<K,V> next;// 构造方法和其他实现...
}
5.1.3 哈希计算
java
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
5.1.4 put方法实现
java
public V put(K key, V value) {return putVal(hash(key), key, value, false, true);
}final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;// 表为空则创建if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;// 计算索引位置if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;// 键已存在if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;// 红黑树节点else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);// 链表节点else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}// 替换值if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;
}
5.1.5 扩容机制
java
final Node<K,V>[] resize() {Node<K,V>[] oldTab = table;int oldCap = (oldTab == null) ? 0 : oldTab.length;int oldThr = threshold;int newCap, newThr = 0;if (oldCap > 0) {if (oldCap >= MAXIMUM_CAPACITY) {threshold = Integer.MAX_VALUE;return oldTab;}else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&oldCap >= DEFAULT_INITIAL_CAPACITY)newThr = oldThr << 1; // 双倍扩容}else if (oldThr > 0) // 初始容量设为阈值newCap = oldThr;else { // 零初始阈值表示使用默认值newCap = DEFAULT_INITIAL_CAPACITY;newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);}if (newThr == 0) {float ft = (float)newCap * loadFactor;newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?(int)ft : Integer.MAX_VALUE);}threshold = newThr;@SuppressWarnings({"rawtypes","unchecked"})Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];table = newTab;if (oldTab != null) {for (int j = 0; j < oldCap; ++j) {Node<K,V> e;if ((e = oldTab[j]) != null) {oldTab[j] = null;if (e.next == null)newTab[e.hash & (newCap - 1)] = e;else if (e instanceof TreeNode)((TreeNode<K,V>)e).split(this, newTab, j, oldCap);else { // 保持顺序Node<K,V> loHead = null, loTail = null;Node<K,V> hiHead = null, hiTail = null;Node<K,V> next;do {next = e.next;if ((e.hash & oldCap) == 0) {if (loTail == null)loHead = e;elseloTail.next = e;loTail = e;}else {if (hiTail == null)hiHead = e;elsehiTail.next = e;hiTail = e;}} while ((e = next) != null);if (loTail != null) {loTail.next = null;newTab[j] = loHead;}if (hiTail != null) {hiTail.next = null;newTab[j + oldCap] = hiHead;}}}}}return newTab;
}
5.2 LinkedHashMap源码分析
LinkedHashMap继承自HashMap,通过维护一个双向链表来保持插入顺序或访问顺序。
5.2.1 节点结构
java
static class Entry<K,V> extends HashMap.Node<K,V> {Entry<K,V> before, after;Entry(int hash, K key, V value, Node<K,V> next) {super(hash, key, value, next);}
}
5.2.2 核心字段
java
// 双向链表的头节点
transient LinkedHashMap.Entry<K,V> head;// 双向链表的尾节点
transient LinkedHashMap.Entry<K,V> tail;// 访问顺序(false=插入顺序, true=访问顺序)
final boolean accessOrder;
5.2.3 访问顺序维护
java
void afterNodeAccess(Node<K,V> e) { // 将节点移到链表末尾LinkedHashMap.Entry<K,V> last;if (accessOrder && (last = tail) != e) {LinkedHashMap.Entry<K,V> p =(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;p.after = null;if (b == null)head = a;elseb.after = a;if (a != null)a.before = b;elselast = b;if (last == null)head = p;else {p.before = last;last.after = p;}tail = p;++modCount;}
}
5.3 TreeMap源码分析
TreeMap是基于红黑树的NavigableMap实现,按键的自然顺序或Comparator排序。
5.3.1 节点结构
java
static final class Entry<K,V> implements Map.Entry<K,V> {K key;V value;Entry<K,V> left;Entry<K,V> right;Entry<K,V> parent;boolean color = BLACK;// 构造方法和其他实现...
}
5.3.2 红黑树操作
TreeMap实现了完整的红黑树操作,包括旋转、插入平衡和删除平衡等。
六、并发集合类
Java还提供了一系列线程安全的集合类,位于java.util.concurrent包中。
6.1 ConcurrentHashMap
ConcurrentHashMap是线程安全的HashMap实现,采用分段锁技术(JDK 7)或CAS+synchronized(JDK 8)。
6.1.1 JDK 8实现改进
JDK 8的ConcurrentHashMap摒弃了分段锁,改用:
-
CAS操作
-
synchronized锁单个桶
-
更细粒度的并发控制
6.1.2 核心方法
java
public V put(K key, V value) {return putVal(key, value, false);
}final V putVal(K key, V value, boolean onlyIfAbsent) {if (key == null || value == null) throw new NullPointerException();int hash = spread(key.hashCode());int binCount = 0;for (Node<K,V>[] tab = table;;) {Node<K,V> f; int n, i, fh;if (tab == null || (n = tab.length) == 0)tab = initTable();else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {if (casTabAt(tab, i, null,new Node<K,V>(hash, key, value, null)))break; // no lock when adding to empty bin}else if ((fh = f.hash) == MOVED)tab = helpTransfer(tab, f);else {V oldVal = null;synchronized (f) {if (tabAt(tab, i) == f) {if (fh >= 0) {binCount = 1;for (Node<K,V> e = f;; ++binCount) {K ek;if (e.hash == hash &&((ek = e.key) == key ||(ek != null && key.equals(ek)))) {oldVal = e.val;if (!onlyIfAbsent)e.val = value;break;}Node<K,V> pred = e;if ((e = e.next) == null) {pred.next = new Node<K,V>(hash, key,value, null);break;}}}else if (f instanceof TreeBin) {Node<K,V> p;binCount = 2;if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,value)) != null) {oldVal = p.val;if (!onlyIfAbsent)p.val = value;}}}}if (binCount != 0) {if (binCount >= TREEIFY_THRESHOLD)treeifyBin(tab, i);if (oldVal != null)return oldVal;break;}}}addCount(1L, binCount);return null;
}
6.2 CopyOnWriteArrayList
CopyOnWriteArrayList是线程安全的List实现,采用写时复制技术。
6.2.1 核心思想
-
读操作无锁
-
写操作复制底层数组
-
适用于读多写少的场景
6.2.2 添加元素
java
public boolean add(E e) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}
}
七、集合框架的性能比较
7.1 List实现性能比较
操作 | ArrayList | LinkedList |
---|---|---|
get(int) | O(1) | O(n) |
add(E) | O(1) 摊销 | O(1) |
add(int, E) | O(n) | O(1) |
remove(int) | O(n) | O(1) |
remove(E) | O(n) | O(n) |
7.2 Set实现性能比较
操作 | HashSet | LinkedHashSet | TreeSet |
---|---|---|---|
add(E) | O(1) | O(1) | O(log n) |
contains(E) | O(1) | O(1) | O(log n) |
remove(E) | O(1) | O(1) | O(log n) |
迭代顺序 | 无 | 插入顺序 | 排序顺序 |
7.3 Map实现性能比较
操作 | HashMap | LinkedHashMap | TreeMap |
---|---|---|---|
put(K,V) | O(1) | O(1) | O(log n) |
get(K) | O(1) | O(1) | O(log n) |
remove(K) | O(1) | O(1) | O(log n) |
迭代顺序 | 无 | 插入/访问顺序 | 排序顺序 |
八、集合框架的最佳实践
-
选择合适的集合类:
-
需要快速随机访问:ArrayList
-
频繁插入删除:LinkedList
-
去重:HashSet
-
键值对:HashMap
-
排序:TreeSet/TreeMap
-
-
初始化合适容量:
-
对于已知大小的集合,指定初始容量避免扩容开销
-
ArrayList: new ArrayList(100)
-
HashMap: new HashMap(256, 0.75f)
-
-
合理使用泛型:
java
// 好 List<String> list = new ArrayList<>();// 不好 List list = new ArrayList();
-
遍历集合的选择:
-
随机访问列表:for循环
-
顺序访问列表:增强for循环或迭代器
-
并行处理:Java 8 Stream API
-
-
线程安全考虑:
-
单线程:普通集合类
-
多线程读多写少:CopyOnWriteArrayList
-
高并发Map:ConcurrentHashMap
-
同步包装:Collections.synchronizedXXX()
-
-
避免在迭代中修改集合:
-
使用迭代器的remove()方法
-
或使用CopyOnWriteArrayList
-
-
重写hashCode()和equals():
-
作为HashMap键或HashSet元素的类必须正确实现这两个方法
-
遵循约定:相等对象必须有相同hashCode
-
-
利用Java 8新特性:
java
map.computeIfAbsent(key, k -> new ArrayList<>()).add(value); list.removeIf(e -> e == null);
九、常见问题与解决方案
9.1 集合与数组转换
java
// 集合转数组
List<String> list = new ArrayList<>();
String[] array = list.toArray(new String[0]);// 数组转集合
List<String> list = Arrays.asList(array); // 固定大小
List<String> list = new ArrayList<>(Arrays.asList(array)); // 可变
9.2 集合的不可变视图
java
List<String> immutableList = Collections.unmodifiableList(list);
Set<String> immutableSet = Collections.unmodifiableSet(set);
Map<K,V> immutableMap = Collections.unmodifiableMap(map);
9.3 空集合与单元素集合
java
List<String> emptyList = Collections.emptyList();
Set<String> singletonSet = Collections.singleton("item");
Map<String,String> singletonMap = Collections.singletonMap("key", "value");
9.4 集合排序
java
// 自然排序
Collections.sort(list);// 自定义排序
Collections.sort(list, (a, b) -> a.length() - b.length());// Java 8方式
list.sort(Comparator.comparing(String::length));
十、总结
Java集合框架是Java语言中最重要、最常用的API之一。通过深入理解其源码实现,我们可以:
-
更高效地使用集合类
-
根据场景选择最合适的实现
-
避免常见的陷阱和性能问题
-
编写更健壮、更高效的代码
从设计角度看,集合框架体现了多种优秀的设计原则和模式:
-
接口与实现分离
-
算法与数据结构分离
-
迭代器模式
-
策略模式
-
模板方法模式
随着Java版本的演进,集合框架也在不断优化和改进,如Java 8引入的Stream API和Lambda表达式使集合操作更加简洁和强大。作为Java开发者,深入理解集合框架的内部机制是提升编程能力的重要一步。
相关文章:
(二十一)Java集合框架源码深度解析
一、集合框架概述 Java集合框架(Java Collections Framework, JCF)是Java语言中用于存储和操作数据集合的一套标准架构。它提供了一组接口、实现类和算法,使开发者能够高效地处理各种数据结构。 1.1 集合框架的历史演变 在Java 1.2之前,Java只有几种简…...
spark数据的提取和保存
Spark数据提取和保存 一、数据提取(读取数据) 1. 读取文件(文本、CSV、JSON等) scala // 读取文本文件 val textData spark.read.text("路径/文件.txt") // 读取CSV文件(带表头) val csvD…...
Graphics——基于.NET 的 CAD 图形预览技术研究与实现——CAD c#二次开发
一、Graphics 类的本质与作用 Graphics 是 .NET 框架中 System.Drawing 命名空间下的核心类,用于在二维画布(如 Bitmap 图像)上绘制图形、文本或图像。它相当于 “绘图工具”,提供了一系列方法(如 DrawLine、FillElli…...
vue3_flask实现mysql数据库对比功能
实现对mysql中两个数据库的表、表结构、表数据的对比功能, 效果如下图 基础环境请参考 vue3flasksqlite前后端项目实战 代码文件结构变化 api/ # 后端相关 ├── daos/ │ ├── __init__.py │ └── db_compare_dao.py # 新增 ├── routes/ │ ├── _…...
【数据结构】2-3-1单链表的定义
数据结构知识点合集 知识点 单链表存储结构 优点:不要求大片连续空间,改变容量方便;缺点:不可随机存取,要耗费一定空间存放指针 /*单链表节点定义*/ typedef struct LNode{ElemType data;struct LNode *next; }LNo…...
面试题总结一
第一天 1. 快速排序 public class QuickSort {public static void quickSort(int[] arr, int low, int high) {if (low < high) {// 分区操作,获取基准元素的最终位置int pivotIndex partition(arr, low, high);// 递归排序基准元素左边的部分quickSort(arr, …...
Ubuntu24.04下安装ISPConfig全过程记录
今天在网上看到ISPConfig,觉得不错,刚好手里又有一台没用的VPS,就顺手安装一个玩玩。具体安装步骤如下: 一、配置服务器hosts及hostname 【安装时候需要检查】 使用root账号登录VPS后 先安装vim编辑器,然后编辑hosts࿰…...
【NGINX】 -10 keepalived + nginx + httpd 实现的双机热备+ 负载均衡
文章目录 1、主架构图1.1 IP地址规划 2、web服务器操作3、配置nginx服务器的负载均衡4、配置keepalived4.1 master4.1 backup 5、测试双机热备5.1 两台keepalived服务器均开启5.2 模拟master节点故障 1、主架构图 1.1 IP地址规划 服务器IP地址web1192.168.107.193web2192.168.…...
NC016NC017美光固态芯片NC101NC102
NC016NC017美光固态芯片NC101NC102 在存储技术的演进历程中,美光科技的NC016、NC017、NC101与NC102系列固态芯片,凭借其技术创新与市场适应性,成为行业关注的焦点。本文将从技术内核、产品性能、行业动向、应用场景及市场价值五个维度&#…...
C++(22):fstream的一些成员函数
目录 1 遍历读取文件 1.1 eof()方法 2 读取文件大小 2.1 seekg() 2.2 tellg() 2.3 代码实例 3 存取文字 3.1 read() 3.2 write() 3.3 代码实例 3.3.1 存取文字 3.3.2 特殊方法存储 3.3.3 特殊方法读取 4 重载的输入输出 4.1 重载的输出 << 4.2 重载的输…...
【网络】Wireshark练习3 analyse DNS||ICMP and response message
ip.addr 172.16.0.100 && ip.addr 172.16.0.5 && (dns || icmp) 包号 22–31 之所以被选中,是因为在整个抓包文件里,与执行 ping cat.inx251.edu.au 这一事件相关的所有报文,恰好连续出现在第 22 到第 31 条记录中。具体分…...
GBS 8.0服装裁剪计划软件在线试用
1、全新升级内核8.0,分床更合理,铺布床数更少; 2、支持SS AUTONESTER排料引擎切换 3、支持ASTM AAMA及国产CAD(如布衣)导出的DXF,Prj文件等 4、核心引擎优化 拖料优化 省料优化 5、经实战对比人工&…...
顺 序 表:数 据 存 储 的 “ 有 序 阵 地 ”
顺 序 表:数 据 存 储 的 “ 有 序 阵 地 ” 线 性 表顺 序 表 - - - 顺 序 存 储 结 构顺 序 表 的 操 作 实 现代 码 全 貌 与 功 能 介 绍顺 序 表 的 功 能 说 明代 码 效 果 展 示代 码 详 解SeqList.hSeqList.ctest.c 总 结 💻作 者 简 介…...
#Redis黑马点评#(七)实战篇完结
目录 一 达人探店 1 发布探店笔记 2 查看探店笔记 3 点赞功能 编辑 4 点赞排行榜(top5) 编辑 二 好友关注 1 关注与取关 2 共同关注 3 Feed流实现关注推送 4 实现滚动分页查询 三 附近商店 1 GEO数据结构 2 附近商户搜索功能 四 用户…...
初始C++:类和对象(中)
概述:本篇博客主要介绍类和对象的相关知识。 1. 类的默认成员函数 默认成员函数就是用户没有显示实现,编译器会自动生成的成员函数称为默认成员函数。一个类,在不写任何代码的情况下编译器会默认生成以下六个默认函数,在六个默认…...
Java开发经验——阿里巴巴编码规范实践解析3
摘要 本文深入解析了阿里巴巴编码规范中关于错误码的制定与管理原则,强调错误码应便于快速溯源和沟通标准化,避免过于复杂。介绍了错误码的命名与设计示例,推荐采用模块前缀、错误类型码和业务编号的结构。同时,探讨了项目错误信…...
ChatGPT:OpenAI Codex—一款基于云的软件工程 AI 代理,赋能 ChatGPT,革新软件开发模式
ChatGPT:OpenAI Codex—一款基于云的软件工程 AI 代理,赋能 ChatGPT,革新软件开发模式 导读:2025年5月16日,OpenAI 发布了 Codex,一个基于云的软件工程 AI 代理,它集成在 ChatGPT 中,…...
iOS 内存分区
iOS内存分区 文章目录 iOS内存分区前言五大分区static、extern、const关键字比较conststaticextern与.h文件的关系extern引用变量extern声明 static和const联合使用extern和const联合使用 前言 笔者之前学习OC源码的时候,发现对于这里的几个static,extern,const的内容有遗忘,所…...
LWIP的Socket接口
Socket接口简介 类似于文件操作的一种网络连接接口,通常将其称之为“套接字”。lwIP的Socket接口兼容BSD Socket接口,但只实现完整Socket的部分功能 netconn是对RAW的封装 Socket是对netconn的封装 SOCKET结构体 struct sockaddr { u8_t sa_len; /* 长…...
【Linux笔记】——线程同步条件变量与生产者消费者模型的实现
🔥个人主页🔥:孤寂大仙V 🌈收录专栏🌈:Linux 🌹往期回顾🌹:【Linux笔记】——线程互斥与互斥锁的封装 🔖流水不争,争的是滔滔不息 一、线程同步的…...
Popeye
概览与定位 Popeye 是由 derailed 团队开源的 Kubernetes 集群资源 “Sanitizer”,它以只读方式扫描集群内的各种资源(如 Pod、Service、Ingress、PVC、RBAC 等),并基于社区最佳实践给出问题等级及修复建议,覆盖配置误…...
ES(ES2023/ES14)最新更新内容,及如何减少内耗
截至2023年10月,JavaScript(ECMAScript)的最新版本是 ES2023(ES14)。 ES2023 引入了许多新特性,如findLast、toSorted等,同时优化了性能。通过减少全局变量、避免内存泄漏、优化循环、减少DOM操作、使用Web Workers、懒加载、缓存、高效数据结构和代码压缩,可以显著降低…...
电子数据取证(数字取证)技术全面指南:从基础到实践
为了后续查阅方便,推荐工具先放到前面 推荐工具 数字取证基础工具 综合取证平台 工具名称类型主要功能适用场景EnCase Forensic商业全面的证据获取和分析、强大的搜索能力法律诉讼、企业调查FTK (Forensic Toolkit)商业高性能处理和索引、集成内存分析大规模数据处…...
【通用智能体】Serper API 详解:搜索引擎数据获取的核心工具
Serper API 详解:搜索引擎数据获取的核心工具 一、Serper API 的定义与核心功能二、技术架构与核心优势2.1 技术实现原理2.2 对比传统方案的突破性优势 三、典型应用场景与代码示例3.1 SEO 监控系统3.2 竞品广告分析 四、使用成本与配额策略五、开发者注意事项六、替…...
基于 STM32 的手持式安检金属探测器设计与实现
一、硬件设计:芯片与功能模块选型及接线 1. 主控芯片选型 芯片型号:STM32F103C8T6 核心优势: 32 位 Cortex-M3 内核,主频 72MHz,满足实时数据处理需求64KB Flash+20KB SRAM,支持程序存储与数据缓存丰富外设:2 路 USART、2 路 SPI、1 路 I2C、12 位 ADC,适配多模块通信…...
虚幻引擎5-Unreal Engine笔记之Default Pawn与GamMode、Camera的关系
虚幻引擎5-Unreal Engine笔记之Default Pawn与GamMode、Camera的关系 code review! 文章目录 虚幻引擎5-Unreal Engine笔记之Default Pawn与GamMode、Camera的关系1.Default Pawn与Camera的关系1.1. Default Pawn 是什么?1.2. Default Pawn 的主要组件1.3. Default…...
Spring源码主线全链路拆解:从启动到关闭的完整生命周期
Spring源码主线全链路拆解:从启动到关闭的完整生命周期 一文看懂 Spring 框架从启动到销毁的主线流程,结合原理、源码路径与伪代码三位一体,系统学习 Spring 底层机制。 1. 启动入口与环境准备 原理说明 Spring Boot 应用入口是标准 Java 应…...
飞帆控件:可配置post/get接口
先上链接: post_get_ithttps://fvi.cn/796看一下这个控件的配置: 当 url 有某个 get 参数时,例如某些接口回传的参数。使用这个接口会发生这些: 如果检测到 url 中有该 url 参数则继续执行选择是否从 url 中删除该参数将这个参数…...
Android 自定义悬浮拖动吸附按钮
一个悬浮的拨打电话按钮,使用CardViewImageView可能会出现适配问题,也就是图片显示不全,出现这种问题,就直接替换控件了,因为上述的组合控件没有FloatingActionButton使用方便,还可以有拖动和吸附效果不是更…...
Spring AI Alibaba集成阿里云百炼大模型应用
文章目录 1.准备工作2.引入maven依赖3.application.yml4.调用4.1.非流式调用4.2.流式调用 阿里云百炼推出的智能体应用、工作流应用和智能体编排应用,有效解决了大模型在处理私有领域问题、获取最新信息、遵循固定流程以及自动规划复杂项目等方面的局限,…...
UI-TARS本地部署
UI-TARS本地部署 UI-TARS本地部署 UI-TARS 论文(arXiv) UI-TARS 官方仓库:包含部署指南、模型下载链接及示例代码。 UI-TARS-Desktop 客户端:支持本地桌面应用的交互控制。 模型部署框架:vLLM本地部署 1.下载项目…...
如何利用内网穿透实现Cursor对私有化部署大模型的跨网络访问实践
文章目录 前言1.安装Ollama2.QwQ-32B模型安装与运行3.Cursor安装与配置4. 简单使用测试5. 调用本地大模型6. 安装内网穿透7. 配置固定公网地址总结 前言 本文主要介绍如何在Windows环境下,使用Cursor接入Ollama启动本地部署的千问qwq-32b大模型实现辅助编程&#x…...
Linux的进程概念
目录 1、冯诺依曼体系结构 2、操作系统(Operating System) 2.1 基本概念 编辑 2.2 目的 3、Linux的进程 3.1 基本概念 3.1.1 PCB 3.1.2 struct task_struct 3.1.3 进程的定义 3.2 基本操作 3.2.1 查看进程 3.2.2 初识fork 3.3 进程状态 3.3.1 操作系统的进程状…...
(10)python开发经验
文章目录 1 cp35 cp36什么意思2 找不到pip3 subprocess编码错误4 导出依赖文件包含路径5 使用自己编译的python并且pyinstall打包程序 更多精彩内容👉内容导航 👈👉Qt开发 👈👉python开发 👈 1 cp35 cp36什…...
什么是时间戳?怎么获取?有什么用
时间戳的定义 时间戳(Timestamp)是指记录某个事件发生的具体时间点,通常以特定的格式表示。它可以精确到秒、毫秒甚至更小的单位,用于标识某个时刻在时间轴上的位置。 获取时间戳的方法 在不同的编程语言中,获取时间…...
Zookeeper 入门(二)
4. Zookeeper 的 ACL 权限控制( Access Control List ) Zookeeper 的ACL 权限控制,可以控制节点的读写操作,保证数据的安全性,Zookeeper ACL 权 限设置分为 3 部分组成,分别是:权限模式(Scheme)、授权对象(…...
[创业之路-361]:企业战略管理案例分析-2-战略制定-使命、愿景、价值观的失败案例
一、失败案例 1、使命方面的失败案例 真功夫创业者内乱:真功夫在创业过程中,由于股权结构不合理,共同创始人及公司大股东潘宇海与实际控制人、董事长蔡达标产生管理权矛盾。双方在公司发展方向、管理改革等方面无法达成一致,导致…...
dijkstra算法加训上 之 分层图最短路
来几个分层图的题练习下哈 P4568 [JLOI2011] 飞行路线 P4568 [JLOI2011] 飞行路线 - 洛谷https://www.luogu.com.cn/problem/P4568 题目描述 Alice 和 Bob 现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在 n 个城市设有业务,设这…...
赋予AI更强的“思考”能力
刚刚!北大校友、OpenAI前安全副总裁Lilian Weng最新博客来了:Why We Think 原文链接:Why We Think by Lilian Weng 这篇文章关注:如何让AI不仅仅是“知道”答案,更能“理解”问题并推导出答案。通过赋予AI更强的“思…...
微服务项目->在线oj系统(Java版 - 1)
相信自己,终会成功 目录 C/S架构与B/S架构 C/S架构(Client/Server,客户端/服务器架构) 特点: 优点: 缺点: 典型应用: B/S架构(Browser/Server,浏览器/服务器架构&a…...
【深度学习】使用块的网络(VGG)
虽然 AlexNet 证明深层神经网络卓有成效,但它没有提供一个通用的模板来指导后续的研究人员设计新的网络。 也就是说尽管我知道了更深更大的网络更有效,但是不清楚怎么让它更深更大,从而起到一个更好的效果。 于是,研究人员开始从单…...
Python数据可视化 - Pyecharts绘图示例
文章目录 一、Pyecharts简介及安装1. Pyecharts简介2. 安装Pyecharts 二、准备数据三、饼图示例1. 初始化选项配置2. 饼图相关设置3. 全局配置项3.1 标题配置项3.2 图例配置项3.3 提示框配置项3.4 工具箱配置项3.5 视觉映射配置项 4. 系列配置项4.1 标签选项配置4.2 图元样式配…...
Day29
复习日 知识点回顾 类的装饰器装饰器思想的进一步理解:外部修改、动态类方法的定义:内部定义和外部定义 作业:复习类和函数的知识点,写下自己过去29天的学习心得,如对函数和类的理解,对python这门工具的理…...
Python列表全面解析:从入门到精通
文章目录 Python列表全面解析:从入门到精通一、列表基础1. 什么是列表?2. 列表特性总结表 二、列表的基本操作(基础)1. 访问元素2. 修改列表 三、列表的常用方法(基础)1. 添加元素的方法2. 删除元素的方法3. 查找和统计方法4. 排序和反转 四、列表的高级…...
Nacos数据写入流程
在 3 节点的 Nacos 集群中,数据写入流程和主节点(Leader)的角色基于 Nacos 的分布式一致性协议(通常使用 Raft 协议)来实现。以下以 Markdown 格式详细说明 3 节点 Nacos 集群的数据写入流程以及主节点的角色和确定方式…...
《P4551 最长异或路径》
题目描述 给定一棵 n 个点的带权树,结点下标从 1 开始到 n。寻找树中找两个结点,求最长的异或路径。 异或路径指的是指两个结点之间唯一路径上的所有边权的异或。 输入格式 第一行一个整数 n,表示点数。 接下来 n−1 行,给出…...
Ansible模块——文件属性查看,文件或目录创建和属性修改
ansible.builtin.stat 可以查看文件信息。 选项 类型 默认值 描述 pathstrnull 要检查的文件或目录的完整路径(必需)。 followboolfalse 如果是符号链接,是否跟随到目标路径上获取其状态。 get_attributesbooltrue 是否返回扩展属性&#…...
【图像生成大模型】Wan2.1:下一代开源大规模视频生成模型
Wan2.1:下一代开源大规模视频生成模型 引言Wan2.1 项目概述核心技术1. 3D 变分自编码器(Wan-VAE)2. 视频扩散 Transformer(Video Diffusion DiT)3. 数据处理与清洗 项目运行方式与执行步骤1. 环境准备2. 安装依赖3. 模…...
AGI大模型(25):LangChain提示词模版
我们也可以创建prompt template, 并引入一些变量到prompt template中,这样在应用的时候更加灵活。 1 代码实现 # 我们也可以创建prompt template, 并引入一些变量到prompt template中,这样在应用的时候更加灵活 from langchain_core.prompts import ChatPromptTemplate from…...
mybatis中的resultMap的association及collectio的使用
目录 1.reusltmap的说明 2.association的使用 3.collection的使用 4.总结 1.reusltmap的说明 resultmap定义了数据库的结果映射到java对象的规则,resultmap包含4个属性: id: ResultMap 的唯一标识 type: 映射到的 Java 类型(全限定类名或…...