Java 中 Map 常用类和数据结构详解
1. 引言
在Java编程中,Map
是一种重要的数据结构,广泛应用于各种场景,Map
实现了键值对(key-value)的存储方式,使得开发者能够快速检索、更新和操作数据。本篇文章将详细讲解Java中常用的Map
类及其底层数据结构,并通过电商交易系统中的实际应用场景来分析每种Map
的使用场景和区别。
2. HashMap
2.1 HashMap 的实现原理
HashMap
是 Java 中常用的一个用于存储键值对的集合类,它以哈希表的形式实现,能够提供快速的数据访问。HashMap
通过键的哈希码(hash code)来定位存储的桶(bucket),并通过不同的处理机制来处理哈希冲突。
2.1.1 HashMap 的基本原理
HashMap 的基本结构是一个数组,每个数组位置称为一个桶(bucket)。每个桶存储的内容可以是一个单独的键值对,也可以是多个键值对的链表或红黑树。在插入数据时,HashMap
首先通过哈希函数根据键的哈希码计算出该键应该存储在哪个桶中,然后将该键值对存储在相应的桶里。
当多个键通过哈希函数得到的桶索引相同时,称为哈希冲突。为了解决哈希冲突,早期版本的HashMap
会将所有冲突的键值对存储为一个链表,从 Java 8 开始,HashMap
在链表长度超过一定阈值后(默认是8),将链表转换为红黑树来优化查询效率。
2.1.2 Java 7及之前的实现
在 Java 7 及之前,HashMap
的每个桶只包含一个简单的链表结构。当出现哈希冲突时,不同的键值对会通过链表链接在一起。链表的结构如下:
- 每个桶包含一个链表的头节点。
- 链表中的每个节点包含了键、值和指向下一个节点的指针。
- 插入和查询操作在链表中都是线性查找,时间复杂度为 O(n),其中 n 是链表的长度。
这种结构在数据量小或冲突少的情况下效率较高,但在哈希冲突严重时,查找的性能会迅速下降为 O(n),因为需要遍历链表的所有节点。
static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;V value;Node<K,V> next;Node(int hash, K key, V value, Node<K,V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}// Map.Entry接口的实现方法
}
2.1.3 Java 8 之后的实现
在 Java 8 中,为了解决哈希冲突严重时性能退化的问题,HashMap
引入了红黑树。当单个桶中的元素数量超过一定阈值(默认是8个)时,HashMap
会将链表转换为红黑树。红黑树是一种自平衡的二叉搜索树,能够保证在最坏情况下的查找、插入和删除操作的时间复杂度为 O(log n)。
核心变化:
- 当链表中的节点数小于阈值时,依旧使用链表。
- 当链表中的节点数超过阈值时,链表转换为红黑树,保证查找和插入操作的效率为 O(log n)。
- 当红黑树的节点数量减少到阈值以下时,会重新退化为链表。
链表转红黑树:
if (binCount >= TREEIFY_THRESHOLD - 1) {treeifyBin(tab, hash);
}
红黑树的结构: 红黑树的实现通过 TreeNode
类完成,TreeNode
继承自 HashMap.Node
,其结构与普通的链表节点不同,额外增加了指向父节点、左子节点和右子节点的引用,以维护红黑树的平衡。
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {TreeNode<K,V> parent;TreeNode<K,V> left;TreeNode<K,V> right;TreeNode<K,V> prev;boolean red;TreeNode(int hash, K key, V value, Node<K,V> next) {super(hash, key, value, next);}
}
2.1.4 链表与红黑树的区别
- 结构不同:链表是线性的,红黑树是一种平衡的二叉树。
- 性能差异:链表的查找时间复杂度是 O(n),而红黑树的查找时间复杂度是 O(log n)。因此,红黑树在元素数量多时性能优于链表。
- 存储结构的转换:当桶中的元素数量超过 8 个时,链表会转换为红黑树;当数量少于 6 个时,红黑树会退化为链表。
2.1.5 详细实现机制
HashMap
的哈希函数和哈希冲突处理机制是其核心部分。HashMap
通过对键的哈希码进行一系列运算,来确保散列的均匀性并避免哈希冲突。在处理冲突时,如果桶中的元素较少,HashMap
采用链表结构;如果元素较多,则采用红黑树,以保证性能的稳定性。
以下是HashMap
中几个重要的阈值:
- DEFAULT_INITIAL_CAPACITY:默认的初始容量为 16。
- DEFAULT_LOAD_FACTOR:默认的负载因子为 0.75。
- TREEIFY_THRESHOLD:链表转为红黑树的阈值为 8。
- UNTREEIFY_THRESHOLD:红黑树转为链表的阈值为 6。
- MIN_TREEIFY_CAPACITY:最小的树化容量为 64,避免在低容量时频繁转换。
2.1.6 HashMap 底层结构类图
2.1.7 总结
- Java 7及之前:
HashMap
通过链表处理哈希冲突,查找时间复杂度为 O(n)。 - Java 8及之后:
HashMap
引入了红黑树,当冲突较少时使用链表,冲突严重时使用红黑树,查找时间复杂度优化为 O(log n)。 - 链表与红黑树的转换:当链表节点超过阈值时会转换为红黑树,红黑树的查找和插入效率更高;当树中节点减少时,会退化为链表。
通过这种机制,HashMap
在 Java 8 之后进一步提升了在高冲突情况下的性能,使其在大规模数据存储中更高效。
2.2 适用场景
适用于大多数查询操作频繁的场景,例如订单查询、商品详情查询等。
2.2.1 提高性能的 HashMap List 转 Map 的电商案例
在电商系统中,我们经常需要处理大量的商品信息。通常商品信息以 List
形式存储,但在查询某个商品时,List
结构的查询效率较低,需要遍历整个列表。如果能将 List
转换为 Map
,利用 HashMap
的 O(1) 查询效率,可以显著提升性能。
问题描述:
在一个电商系统中,商品信息通常以 List
形式存储。当用户进行商品搜索时,系统需要根据商品 ID 获取详细信息。假设我们有大量商品数据,List
结构下每次搜索都需要遍历列表,导致查询速度较慢,如何提高查询效率?
示例:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;class Product {String id;String name;double price;public Product(String id, String name, double price) {this.id = id;this.name = name;this.price = price;}public String getId() {return id;}@Overridepublic String toString() {return "Product{id='" + id + "', name='" + name + "', price=" + price + '}';}
}public class ListToMapExample {// 模拟一个获取商品列表的操作public static List<Product> getProductList() {List<Product> productList = new ArrayList<>();productList.add(new Product("101", "Laptop", 999.99));productList.add(new Product("102", "Smartphone", 699.99));productList.add(new Product("103", "Tablet", 299.99));return productList;}// 将List转换为Map,商品ID为key,商品对象为valuepublic static Map<String, Product> convertListToMap(List<Product> productList) {Map<String, Product> productMap = new HashMap<>();for (Product product : productList) {productMap.put(product.getId(), product);}return productMap;}public static void main(String[] args) {List<Product> productList = getProductList();// 转换 List 为 MapMap<String, Product> productMap = convertListToMap(productList);// 根据商品ID查询商品String searchId = "102";if (productMap.containsKey(searchId)) {System.out.println("Product found: " + productMap.get(searchId));} else {System.out.println("Product not found");}}
}
解决方式:
- 使用
HashMap
代替List
作为商品存储的结构,将商品 ID 作为HashMap
的键,这样在查询商品时只需 O(1) 的复杂度,而不再需要遍历整个列表。 - 示例中展示了如何将
List
转换为HashMap
,并基于商品 ID 高效查询商品信息。
优化效果:
相比原先的 List
结构,使用 HashMap
之后的查询性能显著提升,尤其在处理大规模商品数据时更加高效。
2.2.2 使用 HashMap
提高楼梯算法的查询效率
问题描述:
楼梯问题是经典的递归问题:假设楼梯有 n
级台阶,每次可以走 1 级或 2 级,问有多少种走法?在大规模计算时,递归方式效率较低。如何通过 HashMap
来加速查询,提高算法性能?
示例问题:
你需要通过递归计算楼梯的走法总数。然而,随着台阶数的增加,递归的重复计算严重影响了效率。如何优化这个过程?
楼梯问题递归解法:
public class StaircaseProblem {// 递归实现楼梯走法public static int countWays(int n) {if (n == 0 || n == 1) {return 1;}return countWays(n - 1) + countWays(n - 2);}public static void main(String[] args) {int n = 10; // 假设楼梯有10级System.out.println("Ways to climb " + n + " stairs: " + countWays(n));}
}
问题分析:
上述递归实现效率较低,因为每次计算都会重复进行许多不必要的运算。比如,计算 countWays(10)
会调用多次 countWays(9)
和 countWays(8)
,导致大量重复计算。
解决方式:使用 HashMap
优化递归(记忆化递归)
通过 HashMap
来缓存已经计算过的楼梯走法,将之前计算过的结果存储起来,避免重复计算。
优化后的代码:
import java.util.HashMap;
import java.util.Map;public class OptimizedStaircaseProblem {// 使用 HashMap 缓存已计算的结果private static Map<Integer, Integer> memo = new HashMap<>();public static int countWays(int n) {if (n == 0 || n == 1) {return 1;}// 如果已经计算过,直接返回缓存的结果if (memo.containsKey(n)) {return memo.get(n);}// 计算结果并存入缓存int result = countWays(n - 1) + countWays(n - 2);memo.put(n, result);return result;}public static void main(String[] args) {int n = 10;System.out.println("Ways to climb " + n + " stairs: " + countWays(n));}
}
优化方式分析:
- 使用
HashMap
来缓存已经计算过的台阶数对应的走法数。 - 每次递归时,先检查
HashMap
是否已经包含结果,如果有,直接返回,不再重复计算。 - 通过记忆化递归,极大减少了重复计算的次数,从而提升了算法效率。
解决效果:
通过使用 HashMap
,我们将原本的递归解法优化为一种动态规划的思路,大幅度降低了时间复杂度,从指数级(O(2^n))降低为线性级(O(n)),适合在大规模输入下的高效计算。
3. LinkedHashMap
LinkedHashMap
是 Java 集合框架中的一种基于 HashMap
实现的有序映射类。与 HashMap
不同,LinkedHashMap
维护了键值对的插入顺序或访问顺序,因此它提供了一个有序的迭代方式。LinkedHashMap
的主要特点是能够在保证键值对唯一性的同时,还能按顺序访问键值对。
3.1 LinkedHashMap 的特点
- 有序性
LinkedHashMap
保证了元素的迭代顺序。默认情况下,元素的迭代顺序与插入顺序一致。但可以通过构造函数设置为根据访问顺序(即最近最少使用策略 LRU)来迭代元素。 - 插入和访问顺序的选择
可以选择在元素被访问后(如通过get()
、put()
等方法)将该元素移到链表的尾部,从而按照访问顺序来迭代元素。适用于实现缓存等场景。 - 线程不安全
与HashMap
类似,LinkedHashMap
也是线程不安全的。如果在多线程环境中使用LinkedHashMap
,需要对其进行手动同步或者使用ConcurrentHashMap
作为替代。
3.2 LinkedHashMap 的适用场景
- 缓存系统
LinkedHashMap
非常适合实现缓存系统,尤其是那些基于 LRU 策略的缓存。通过LinkedHashMap
的removeEldestEntry
方法,可以实现当元素数量超过某个限制时自动移除最旧的元素。 - 需要按顺序遍历的场景
在一些需要按插入顺序或访问顺序来遍历键值对的场景,LinkedHashMap
可以很好地满足需求。
3.3 在电商系统中的应用
在电商系统中,用户的购物车是一种常见的缓存场景。为了优化性能,可以将用户最近添加到购物车的商品信息缓存到内存中。当购物车中的商品数量超过一定数量时,自动移除最早加入的商品。
代码示例:购物车缓存系统
以下示例代码展示了如何使用 LinkedHashMap
实现一个购物车的缓存系统,当购物车中的商品数量超过 5 时,自动移除最早加入的商品。
import java.util.LinkedHashMap;
import java.util.Map;public class ShoppingCart {private static final int MAX_CART_SIZE = 5;// 使用 LinkedHashMap 实现购物车缓存,并设置访问顺序private LinkedHashMap<String, Integer> cart = new LinkedHashMap<String, Integer>(MAX_CART_SIZE, 0.75f, true) {@Overrideprotected boolean removeEldestEntry(Map.Entry<String, Integer> eldest) {return size() > MAX_CART_SIZE;}};// 添加商品到购物车public void addToCart(String product, int quantity) {cart.put(product, quantity);System.out.println("Added to cart: " + product + ", Quantity: " + quantity);displayCart();}// 显示购物车public void displayCart() {System.out.println("Current cart contents: " + cart);}public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();cart.addToCart("ProductA", 1);cart.addToCart("ProductB", 2);cart.addToCart("ProductC", 3);cart.addToCart("ProductD", 4);cart.addToCart("ProductE", 5);cart.addToCart("ProductF", 6); // 此时最早加入的 ProductA 将被移除}
}
代码说明:
LinkedHashMap
通过重写removeEldestEntry
方法实现了当元素数量超过MAX_CART_SIZE
(5 个)时,自动移除最旧的商品。addToCart
方法用于将商品添加到购物车,displayCart
方法用于显示当前购物车内容。- 当加入第 6 个商品时,购物车中最早添加的商品
ProductA
会被移除。
3.4 LinkedHashMap 的性能分析
LinkedHashMap
在保证有序性的同时,仍然保留了 HashMap
的高效特性,即 O(1) 的查找和插入性能。它通过维护一个双向链表来记录元素的顺序,因而在保持插入和访问顺序的同时,性能损耗较小,非常适合实现有序的缓存系统。
4. TreeMap
TreeMap
是 Java 集合框架中的一个基于红黑树实现的有序映射类。与 LinkedHashMap
按插入顺序或访问顺序进行排序不同,TreeMap
根据键的自然顺序或通过自定义的比较器对键进行排序。
4.1 TreeMap 的特点
- 有序性
TreeMap
保证键的顺序,并且可以根据键的自然排序或通过提供的自定义比较器进行排序。 - 基于红黑树实现
TreeMap
的底层实现基于红黑树(Red-Black Tree),它是一种自平衡二叉搜索树,因此TreeMap
的所有操作(如插入、删除、查找等)都具有 O(log n) 的时间复杂度。 - 线程不安全
与HashMap
和LinkedHashMap
类似,TreeMap
也是线程不安全的,在多线程环境中使用时需要外部同步处理。
4.2 TreeMap 的适用场景
- 需要有序存储的场景
在某些需要按照键的自然顺序或自定义顺序进行排序的场景中,TreeMap
非常适合。例如,电商系统中可以用TreeMap
来管理商品价格或时间敏感的库存。 - 范围查询
由于TreeMap
是有序的,它支持高效的范围查询操作。比如可以在某个范围内查找所有满足条件的键值对,这在一些统计或筛选场景中非常有用。
4.3 在电商系统中的应用
假设在一个电商系统中,我们需要根据商品价格对商品进行排序,并提供按价格范围进行商品筛选的功能。TreeMap
可以轻松实现这一功能。
代码示例:商品价格排序和筛选
以下示例代码展示了如何使用 TreeMap
来管理和筛选商品价格。
import java.util.Map;
import java.util.TreeMap;public class ProductCatalog {// 使用 TreeMap 管理商品价格,并根据价格排序private TreeMap<Double, String> productPrices = new TreeMap<>();// 添加商品及其价格public void addProduct(String product, double price) {productPrices.put(price, product);System.out.println("Added: " + product + " with price: " + price);}// 显示所有商品及其价格public void displayProducts() {for (Map.Entry<Double, String> entry : productPrices.entrySet()) {System.out.println("Product: " + entry.getValue() + ", Price: " + entry.getKey());}}// 按价格范围筛选商品public void filterProductsByPrice(double minPrice, double maxPrice) {Map<Double, String> filteredProducts = productPrices.subMap(minPrice, maxPrice);System.out.println("Products in price range [" + minPrice + ", " + maxPrice + "]:");for (Map.Entry<Double, String> entry : filteredProducts.entrySet()) {System.out.println("Product: " + entry.getValue() + ", Price: " + entry.getKey());}}public static void main(String[] args) {ProductCatalog catalog = new ProductCatalog();catalog.addProduct("ProductA", 10.99);catalog.addProduct("ProductB", 15.99);catalog.addProduct("ProductC", 5.49);catalog.addProduct("ProductD", 25.00);System.out.println("All Products:");catalog.displayProducts();System.out.println("\nProducts in price range [10, 20]:");catalog.filterProductsByPrice(10.00, 20.00);}
}
代码说明:
ProductCatalog
类使用TreeMap
管理商品价格,并根据商品价格进行排序。addProduct
方法将商品及其价格添加到TreeMap
中。filterProductsByPrice
方法使用subMap
来筛选出符合指定价格范围的商品。
4.4 TreeMap 自定义排序
在某些场景中,我们可能希望根据自定义的规则对商品进行排序,而不仅仅是按照自然排序(如价格)。通过提供自定义比较器,我们可以实现多种排序方式。
例如,假设我们需要根据商品名称的长度进行排序,以下是示例代码:
import java.util.Comparator;
import java.util.TreeMap;public class CustomSortProductCatalog {// 自定义比较器:根据商品名称长度排序private TreeMap<String, Double> productCatalog = new TreeMap<>(new Comparator<String>() {@Overridepublic int compare(String product1, String product2) {return Integer.compare(product1.length(), product2.length());}});// 添加商品public void addProduct(String product, double price) {productCatalog.put(product, price);System.out.println("Added: " + product + " with price: " + price);}// 显示商品public void displayProducts() {productCatalog.forEach((product, price) -> System.out.println("Product: " + product + ", Price: " + price));}public static void main(String[] args) {CustomSortProductCatalog catalog = new CustomSortProductCatalog();catalog.addProduct("Short", 10.99);catalog.addProduct("VeryLongProductName", 25.00);catalog.addProduct("Medium", 15.99);System.out.println("All Products sorted by name length:");catalog.displayProducts();}
}
代码说明:
- 通过自定义比较器,
TreeMap
实现了根据商品名称长度对商品进行排序。
5. 深入理解 ConcurrentHashMap
在多线程编程中,线程安全和性能往往是一对矛盾。传统的 HashMap
在多线程环境下是非线程安全的,因此不能直接应用于高并发场景。而 ConcurrentHashMap
作为 Java 的并发集合,提供了线程安全的操作,并且在设计上优化了高并发环境下的性能。这使得它成为多线程程序中处理共享数据时的首选之一,尤其是在电商交易系统等高并发环境中有广泛应用。
5.1 ConcurrentHashMap 的特点
- 线程安全
ConcurrentHashMap
在底层通过分段锁(在 Java 8 之前)或CAS
操作(在 Java 8 及之后)来实现线程安全,保证多个线程可以并发地对集合进行操作,而不会发生数据不一致的情况。相比于使用全局锁的Hashtable
,ConcurrentHashMap
允许更高的并发度,从而减少了性能瓶颈。 - 高性能
在 Java 8 之前,ConcurrentHashMap
使用了分段锁的机制,将哈希表划分成多个段,每个段都拥有自己的锁,这样不同线程在操作不同段的元素时可以并行工作,提升了并发性能。
从 Java 8 开始,ConcurrentHashMap
不再使用分段锁,而是采用CAS
(Compare-And-Swap)操作以及红黑树优化,使得并发性和性能进一步提升。哈希桶中的链表在元素较多时会自动转换为红黑树,提高了大数据量下的查找效率。 - 无锁读操作
ConcurrentHashMap
的读操作不需要加锁,这是通过内部结构设计实现的。当多个线程同时读取数据时,读操作不会阻塞写操作,也不会引起锁竞争,从而提高了并发访问的效率。 - 分片设计
ConcurrentHashMap
通过分片(segments)的设计,将数据划分为多个小片,使得多个线程可以同时访问不同片的内容而不会互相阻塞。这种设计在多线程访问下可以显著减少锁争用,提升并发处理能力。 - 迭代器弱一致性
在ConcurrentHashMap
中,迭代器是弱一致的(weakly consistent)。这意味着在迭代过程中,如果有其他线程对集合进行修改,迭代器不会抛出ConcurrentModificationException
,但它也不会保证获取的内容完全反映当前集合的状态。迭代器所返回的数据是修改之前的快照,因此在高并发下,ConcurrentHashMap
可以保证迭代操作的稳定性。
5.2 ConcurrentHashMap 的适用场景
由于 ConcurrentHashMap
具有线程安全性和高性能的特点,它在以下场景中尤其适用:
- 多线程读多写少的场景
在一些多线程程序中,读操作远远多于写操作,比如缓存系统或者状态监控系统。在这种情况下,ConcurrentHashMap
的无锁读操作可以极大地提高性能,同时保证写操作的安全性。 - 高并发环境中的共享数据
在电商交易系统中,用户会频繁查询商品信息、订单状态等。这些数据往往需要通过共享的哈希表进行管理,因此使用ConcurrentHashMap
可以确保在高并发下对数据进行安全访问。 - 数据频繁更新和查询的场景
例如,统计用户的在线人数、商品点击量等场景中,多个线程需要同时读取和更新数据,而ConcurrentHashMap
可以高效地支持并发的读取和写入操作。
5.3 在电商系统中的应用
在一个电商交易系统中,商品库存管理是一个常见的高并发场景。假设有一个电商平台,成千上万的用户会同时访问某个热门商品的库存信息,甚至会同时进行下单操作。为了保证在高并发情况下库存信息的正确性,必须使用线程安全的数据结构。ConcurrentHashMap
是一个很好的选择,因为它可以保证多个用户同时访问和更新库存时的安全性。
代码示例:商品库存管理
以下是一个使用 ConcurrentHashMap
来管理商品库存的示例代码:
import java.util.concurrent.ConcurrentHashMap;public class InventoryService {// 使用 ConcurrentHashMap 来存储商品库存信息private ConcurrentHashMap<String, Integer> productStock = new ConcurrentHashMap<>();// 初始化库存public InventoryService() {productStock.put("productA", 100);productStock.put("productB", 200);}// 查询库存public int getStock(String productId) {return productStock.getOrDefault(productId, 0);}// 减少库存(下单操作)public boolean reduceStock(String productId, int quantity) {while (true) {Integer stock = productStock.get(productId);if (stock == null || stock < quantity) {return false; // 库存不足,返回失败}// 使用 CAS 操作更新库存int newStock = stock - quantity;if (productStock.replace(productId, stock, newStock)) {return true; // 更新成功,返回成功}}}// 增加库存(商品入库操作)public void addStock(String productId, int quantity) {productStock.merge(productId, quantity, Integer::sum);}public static void main(String[] args) {InventoryService inventoryService = new InventoryService();// 多线程下进行库存查询和更新操作Runnable checkStockTask = () -> {String productId = "productA";System.out.println("当前库存:" + inventoryService.getStock(productId));};Runnable reduceStockTask = () -> {String productId = "productA";boolean success = inventoryService.reduceStock(productId, 1);System.out.println("减少库存操作 " + (success ? "成功" : "失败"));};Thread t1 = new Thread(checkStockTask);Thread t2 = new Thread(reduceStockTask);t1.start();t2.start();}
}
代码说明:
InventoryService
类用于管理商品库存,内部使用了ConcurrentHashMap
来存储商品 ID 与对应的库存量。getStock
方法用于查询商品库存,使用getOrDefault
方法确保即使商品不存在也能返回一个默认值。reduceStock
方法用于减少商品库存,模拟了用户下单时减少库存的操作。该方法使用了CAS
操作,通过replace
方法来确保并发下安全地更新库存。addStock
方法模拟了商品入库操作,使用merge
方法来累加库存,这也是ConcurrentHashMap
提供的一个便捷方法。
相关文章:

Java 中 Map 常用类和数据结构详解
1. 引言 在Java编程中,Map是一种重要的数据结构,广泛应用于各种场景,Map实现了键值对(key-value)的存储方式,使得开发者能够快速检索、更新和操作数据。本篇文章将详细讲解Java中常用的Map类及其底层数据结…...
实时监控,动态调整 —— 淘宝商品详情API助力商家实现灵活经营
在讨论实时监控和动态调整的策略时,虽然我不能直接提供淘宝商品详情API的具体代码(因为这通常涉及商业机密和API密钥等敏感信息),但我可以给出一个概念性的示例,说明如何使用这类API来辅助商家实现灵活经营。 概念性示…...
WebGL常用接口和事件
目录 初始化WebGL上下文清除缓冲区缓冲区对象着色器和程序属性指针渲染事件监听错误处理纹理映射...

Golang | Leetcode Golang题解之第429题N叉树的层序遍历
题目: 题解: func levelOrder(root *Node) (ans [][]int) {if root nil {return}q : []*Node{root}for q ! nil {level : []int{}tmp : qq nilfor _, node : range tmp {level append(level, node.Val)q append(q, node.Children...)}ans append(a…...
数据库的全透明加密和半透明加密主要是针对数据存储安全的不同处理方式
数据库的全透明加密和半透明加密主要是针对数据存储安全的不同处理方式。 全透明加密(也称作无损加密或自动加密)就像是给文字戴上了一层无形的面具。在用户看来,他们在数据库中输入的是明文(比如姓名、密码)…...

MySQL的登录、访问、退出
一、登录: 访问MySQL服务器对应的命令:mysql.exe ,位置:C:\Program Files\MySQL\MySQL Server 8.0\bin (mysql.exe需要带参数执行,所以直接在图形界面下执行该命令会自动结束) 执行mysql.exe命令的时候出…...

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-25
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-25 1. PromSec: Prompt Optimization for Secure Generation of Functional Source Code with Large Language Models (LLMs) M Nazzal, I Khalil, A Khreishah, NH Phan - arXiv preprint arXiv:2409.12699, 2…...
PyTorch框架安装
安装 pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple 介绍 PyTorch 一个 Python 深度学习框架,它将数据封装成张量(Tensor)来进行处理。 PyTorch 中的张量就是元素为 同一种数据 类型的多维矩阵。在 PyTorch 中࿰…...

分布式锁优化之 使用lua脚本改造分布式锁保证判断和删除的原子性(优化之LUA脚本保证删除的原子性)
文章目录 1、lua脚本入门1.1、变量:弱类型1.2、流程控制1.3、在lua中执行redis指令1.4、实战:先判断是否自己的锁,如果是才能删除 2、AlbumInfoApiController --》testLock()3、AlbumInfoServiceImpl --》testLock() 1、lua脚本入门 Lua 教程…...

从安防视频监控行业发展趋势看EasyCVR平台如何驱动行业智能升级
一、市场规模持续增长 随着科技的进步和社会安全意识的提升,安防视频监控行业市场规模持续增长。据市场研究数据显示,全球智能视频监控市场规模已超过千亿美元,并有望在未来几年内保持高速增长。在中国市场,随着智慧城市、工业互…...

TIOBE 编程指数 9 月排行榜公布 VB.Net第七
原文地址:百度安全验证 IT之家 9 月 8 日消息,TIOBE 编程社区指数是一个衡量编程语言受欢迎程度的指标,评判的依据来自世界范围内的工程师、课程、供应商及搜索引擎,今天 TIOBE 官网公布了 2024 年 9 月的编程语言排行榜…...

如何用ChatGPT制作一款手机游戏应用
有没有想过自己做一款手机游戏,并生成apk手机应用呢?有了人工智能,这一切就成为可能。今天,我们就使用ChatGPT来创建一个简单的井字棋游戏(Tic-Tac-Toe),其实这个过程非常轻松且高效。 通过Cha…...
0基础学前端 day4
大家好,欢迎来到无限大的频道。 今天继续带领大家开始0基础学前端。 一、 什么是Bootstrap框架? Bootstrap是一个开源前端框架,于2011年由Twitter的开发团队开发并发布。其主要目的是简化开发过程,并使开发者能够轻松快速地构建…...

功能测试详解
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 一、测试项目启动与研读需求文档 (一) 组建测试团队 1、测试团队中的角色 2、测试团队的基本责任 尽早地发现软件程序、系统或产品中所…...

<Java>String类型变量的使用
两边有一个string就是连接,否则做加法 ‘ ’是char,“ ”是string,char能做加法,string只能连接...
JavaScript可视化
JavaScript 提供了多种库和工具来进行数据可视化。以下是一些流行的可视化库及其特点: D3.js特点: 强大的数据驱动文档(Data-Driven Documents)库,允许创建复杂的交互式图表。使用场景: 适合需要高度自定义和复杂交互的可视化。Chart.js特点: 易于使用的图表库,提供了多种…...

HTML5简介的水果蔬菜在线商城网站源码系列模板3
文章目录 1.设计来源1.1 主界面1.2 商品列表1.3 商品信息1.4 购物车1.5 其他页面效果 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板,程序开发,在线开发,在线沟通 作者:xcLeigh 文章地址:https://blog.csdn.ne…...

传输层TCP协议
一、TCP协议格式 我们看到报头固定有20字节,最后选项大小不固定。 4位首部长度(二进制0000 ~ 1111,十进制范围[0, 15])单位是4字节(存放字节大小范围[0, 60])包括了20字节固定长度 选项长度。若选项大小为…...
自己开发一个网站系列之-网页开发初识
自己开发一个网站系列之-网页开发初识 欢迎来到网页开发的世界!在这个教程中,我们将介绍网页开发的基本概念、工具和技术,让你能够从零开始创建自己的网页。 一、基础概念 1. 什么是网页? 网页是通过互联网进行访问的文档&#…...

【代码随想录训练营第42期 Day61打卡 - 图论Part11 - Floyd 算法与A * 算法
目录 一、Floyd算法与A * 算法 1、Floyd算法 思想 伪代码 2、 A * 算法 思想 伪代码 二、经典题目 题目一:卡码网 97. 小明逛公园 题目链接 题解:Floyd 算法 题目二:卡码网 127. 骑士的攻击 题目链接 题解:A * 算法&a…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...