当前位置: 首页 > news >正文

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 的特点

  1. 有序性
    LinkedHashMap 保证了元素的迭代顺序。默认情况下,元素的迭代顺序与插入顺序一致。但可以通过构造函数设置为根据访问顺序(即最近最少使用策略 LRU)来迭代元素。
  2. 插入和访问顺序的选择
    可以选择在元素被访问后(如通过 get()put() 等方法)将该元素移到链表的尾部,从而按照访问顺序来迭代元素。适用于实现缓存等场景。
  3. 线程不安全
    HashMap 类似,LinkedHashMap 也是线程不安全的。如果在多线程环境中使用 LinkedHashMap,需要对其进行手动同步或者使用 ConcurrentHashMap 作为替代。

3.2 LinkedHashMap 的适用场景

  1. 缓存系统
    LinkedHashMap 非常适合实现缓存系统,尤其是那些基于 LRU 策略的缓存。通过 LinkedHashMapremoveEldestEntry 方法,可以实现当元素数量超过某个限制时自动移除最旧的元素。
  2. 需要按顺序遍历的场景
    在一些需要按插入顺序或访问顺序来遍历键值对的场景,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 的特点

  1. 有序性
    TreeMap 保证键的顺序,并且可以根据键的自然排序或通过提供的自定义比较器进行排序。
  2. 基于红黑树实现
    TreeMap 的底层实现基于红黑树(Red-Black Tree),它是一种自平衡二叉搜索树,因此 TreeMap 的所有操作(如插入、删除、查找等)都具有 O(log n) 的时间复杂度。
  3. 线程不安全
    HashMapLinkedHashMap 类似,TreeMap 也是线程不安全的,在多线程环境中使用时需要外部同步处理。

4.2 TreeMap 的适用场景

  1. 需要有序存储的场景
    在某些需要按照键的自然顺序或自定义顺序进行排序的场景中,TreeMap 非常适合。例如,电商系统中可以用 TreeMap 来管理商品价格或时间敏感的库存。
  2. 范围查询
    由于 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 的特点

  1. 线程安全
    ConcurrentHashMap 在底层通过分段锁(在 Java 8 之前)或 CAS 操作(在 Java 8 及之后)来实现线程安全,保证多个线程可以并发地对集合进行操作,而不会发生数据不一致的情况。相比于使用全局锁的 HashtableConcurrentHashMap 允许更高的并发度,从而减少了性能瓶颈。
  2. 高性能
    在 Java 8 之前,ConcurrentHashMap 使用了分段锁的机制,将哈希表划分成多个段,每个段都拥有自己的锁,这样不同线程在操作不同段的元素时可以并行工作,提升了并发性能。
    从 Java 8 开始,ConcurrentHashMap 不再使用分段锁,而是采用 CAS(Compare-And-Swap)操作以及红黑树优化,使得并发性和性能进一步提升。哈希桶中的链表在元素较多时会自动转换为红黑树,提高了大数据量下的查找效率。
  3. 无锁读操作
    ConcurrentHashMap 的读操作不需要加锁,这是通过内部结构设计实现的。当多个线程同时读取数据时,读操作不会阻塞写操作,也不会引起锁竞争,从而提高了并发访问的效率。
  4. 分片设计
    ConcurrentHashMap 通过分片(segments)的设计,将数据划分为多个小片,使得多个线程可以同时访问不同片的内容而不会互相阻塞。这种设计在多线程访问下可以显著减少锁争用,提升并发处理能力。
  5. 迭代器弱一致性
    ConcurrentHashMap 中,迭代器是弱一致的(weakly consistent)。这意味着在迭代过程中,如果有其他线程对集合进行修改,迭代器不会抛出 ConcurrentModificationException,但它也不会保证获取的内容完全反映当前集合的状态。迭代器所返回的数据是修改之前的快照,因此在高并发下,ConcurrentHashMap 可以保证迭代操作的稳定性。

5.2 ConcurrentHashMap 的适用场景

由于 ConcurrentHashMap 具有线程安全性和高性能的特点,它在以下场景中尤其适用:

  1. 多线程读多写少的场景
    在一些多线程程序中,读操作远远多于写操作,比如缓存系统或者状态监控系统。在这种情况下,ConcurrentHashMap 的无锁读操作可以极大地提高性能,同时保证写操作的安全性。
  2. 高并发环境中的共享数据
    在电商交易系统中,用户会频繁查询商品信息、订单状态等。这些数据往往需要通过共享的哈希表进行管理,因此使用 ConcurrentHashMap 可以确保在高并发下对数据进行安全访问。
  3. 数据频繁更新和查询的场景
    例如,统计用户的在线人数、商品点击量等场景中,多个线程需要同时读取和更新数据,而 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编程中&#xff0c;Map是一种重要的数据结构&#xff0c;广泛应用于各种场景&#xff0c;Map实现了键值对&#xff08;key-value&#xff09;的存储方式&#xff0c;使得开发者能够快速检索、更新和操作数据。本篇文章将详细讲解Java中常用的Map类及其底层数据结…...

实时监控,动态调整 —— 淘宝商品详情API助力商家实现灵活经营

在讨论实时监控和动态调整的策略时&#xff0c;虽然我不能直接提供淘宝商品详情API的具体代码&#xff08;因为这通常涉及商业机密和API密钥等敏感信息&#xff09;&#xff0c;但我可以给出一个概念性的示例&#xff0c;说明如何使用这类API来辅助商家实现灵活经营。 概念性示…...

WebGL常用接口和事件

目录 初始化WebGL上下文清除缓冲区缓冲区对象着色器和程序属性指针渲染事件监听错误处理纹理映射...

Golang | Leetcode Golang题解之第429题N叉树的层序遍历

题目&#xff1a; 题解&#xff1a; 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…...

数据库的全透明加密和半透明加密主要是针对数据存储安全的不同处理方式

数据库的全透明加密和半透明加密主要是针对数据存储安全的不同处理方式。 全透明加密&#xff08;也称作无损加密或自动加密&#xff09;就像是给文字戴上了一层无形的面具。在用户看来&#xff0c;他们在数据库中输入的是明文&#xff08;比如姓名、密码&#xff09;&#xf…...

MySQL的登录、访问、退出

一、登录&#xff1a; 访问MySQL服务器对应的命令&#xff1a;mysql.exe ,位置&#xff1a;C:\Program Files\MySQL\MySQL Server 8.0\bin &#xff08;mysql.exe需要带参数执行&#xff0c;所以直接在图形界面下执行该命令会自动结束&#xff09; 执行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 深度学习框架&#xff0c;它将数据封装成张量&#xff08;Tensor&#xff09;来进行处理。 PyTorch 中的张量就是元素为 同一种数据 类型的多维矩阵。在 PyTorch 中&#xff0…...

分布式锁优化之 使用lua脚本改造分布式锁保证判断和删除的原子性(优化之LUA脚本保证删除的原子性)

文章目录 1、lua脚本入门1.1、变量&#xff1a;弱类型1.2、流程控制1.3、在lua中执行redis指令1.4、实战&#xff1a;先判断是否自己的锁&#xff0c;如果是才能删除 2、AlbumInfoApiController --》testLock()3、AlbumInfoServiceImpl --》testLock() 1、lua脚本入门 Lua 教程…...

从安防视频监控行业发展趋势看EasyCVR平台如何驱动行业智能升级

一、市场规模持续增长 随着科技的进步和社会安全意识的提升&#xff0c;安防视频监控行业市场规模持续增长。据市场研究数据显示&#xff0c;全球智能视频监控市场规模已超过千亿美元&#xff0c;并有望在未来几年内保持高速增长。在中国市场&#xff0c;随着智慧城市、工业互…...

TIOBE 编程指数 9 月排行榜公布 VB.Net第七

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

如何用ChatGPT制作一款手机游戏应用

有没有想过自己做一款手机游戏&#xff0c;并生成apk手机应用呢&#xff1f;有了人工智能&#xff0c;这一切就成为可能。今天&#xff0c;我们就使用ChatGPT来创建一个简单的井字棋游戏&#xff08;Tic-Tac-Toe&#xff09;&#xff0c;其实这个过程非常轻松且高效。 通过Cha…...

0基础学前端 day4

大家好&#xff0c;欢迎来到无限大的频道。 今天继续带领大家开始0基础学前端。 一、 什么是Bootstrap框架&#xff1f; Bootstrap是一个开源前端框架&#xff0c;于2011年由Twitter的开发团队开发并发布。其主要目的是简化开发过程&#xff0c;并使开发者能够轻松快速地构建…...

功能测试详解

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

<Java>String类型变量的使用

两边有一个string就是连接&#xff0c;否则做加法 ‘ ’是char&#xff0c;“ ”是string&#xff0c;char能做加法&#xff0c;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 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.ne…...

传输层TCP协议

一、TCP协议格式 我们看到报头固定有20字节&#xff0c;最后选项大小不固定。 4位首部长度&#xff08;二进制0000 ~ 1111&#xff0c;十进制范围[0, 15]&#xff09;单位是4字节&#xff08;存放字节大小范围[0, 60]&#xff09;包括了20字节固定长度 选项长度。若选项大小为…...

自己开发一个网站系列之-网页开发初识

自己开发一个网站系列之-网页开发初识 欢迎来到网页开发的世界&#xff01;在这个教程中&#xff0c;我们将介绍网页开发的基本概念、工具和技术&#xff0c;让你能够从零开始创建自己的网页。 一、基础概念 1. 什么是网页&#xff1f; 网页是通过互联网进行访问的文档&#…...

【代码随想录训练营第42期 Day61打卡 - 图论Part11 - Floyd 算法与A * 算法

目录 一、Floyd算法与A * 算法 1、Floyd算法 思想 伪代码 2、 A * 算法 思想 伪代码 二、经典题目 题目一&#xff1a;卡码网 97. 小明逛公园 题目链接 题解&#xff1a;Floyd 算法 题目二&#xff1a;卡码网 127. 骑士的攻击 题目链接 题解&#xff1a;A * 算法&a…...

docker和ufw冲突问题

在ubuntu上部署的docker映射的端口&#xff0c;开启防火墙ufw后&#xff0c;在未放通的状态下&#xff0c;还是可以访问 解决办法&#xff1a; 在/etc/docker/daemon.json添加如下配置 {"iptables": false } 然后重启docker服务即可 systemctl daemon-reload s…...

Java(基本数据类型)( ̄︶ ̄)↗

Java 基本数据类型是Java编程语言中用于存储数据值的基本单位。它们直接映射到硬件的处理器上&#xff0c;因此访问速度非常快。Java中的基本数据类型分为四大类&#xff1a;整型、浮点型、字符型、布尔型。每种类型都有其固定的范围和存储大小。 一、整型 1&#xff09;byte…...

283. 移动0

class Solution(object):def moveZeroes(self, nums):""":type nums: List[int]:rtype: None Do not return anything, modify nums in-place instead."""# 两个指针&#xff0c;left, right,中间夹的都是0&#xff0c;# 像个虫子一样一纵一纵的…...

Mysql删库跑路,如何恢复数据?

问题 删库跑路&#xff0c;数据还能恢复吗&#xff1f; 我们经常听说某某被领导训斥了&#xff0c;对领导心生痛恨&#xff0c;然后登录 Mysql 删库跑路。对于闲聊中经常听说过的一个段子&#xff0c;在现实生活中是否真的发生过&#xff0c;如果发生了&#xff0c;我们该如何解…...

【HarmonyOS】应用引用media中的字符串资源如何拼接字符串

【HarmonyOS】应用引用media中的字符串资源如何拼接字符串 一、问题背景&#xff1a; 鸿蒙应用中使用字符串资源加载&#xff0c;一般文本放置在resoutces-base-element-string.json字符串配置文件中。便于国际化的处理。当然小项目一般直接引用字符串&#xff0c;不需要加载s…...

打开ffmpeg编码器的时候报错:avcodec_open2()返回-22

[h264_v4l2m2m 0x555555617a00] Could not find a valid device [h264_v4l2m2m 0x555555617a00] cant configure encoder 前言&#xff1a;先做一个操作&#xff0c;查找编码器的时候&#xff0c;使用名字查找的方式&#xff1a; const AVCodec *avcodec_find_encoder_by_n…...

R包:ggheatmap热图

加载R包 # devtools::install_github("XiaoLuo-boy/ggheatmap")library(ggheatmap) library(tidyr)数据 set.seed(123) df <- matrix(runif(225,0,10),ncol 15) colnames(df) <- paste("sample",1:15,sep "") rownames(df) <- sapp…...

springboot实战学习(7)(JWT令牌的组成、JWT令牌的使用与验证)

接着上篇博客的学习。上篇博客是在基本完成用户模块的注册接口的开发以及注册时的参数合法性校验的基础上&#xff0c;基本完成用户模块的登录接口的主逻辑以及提到了问题&#xff1a;"用户未登录&#xff0c;需要通过登录&#xff0c;获取到令牌进行登录认证&#xff0c;…...

如何使用numpy反转数组

如何使用numpy反转数组 1、使用np.flip()函数 可以使用flip(m, axisNone)函数来对数组进行反转&#xff1a; m:输入数组 axis:为None则行列都反转 axis:为0则反转行 axis:为1则反转列2、代码 import numpy as np# 创建一维数组 arr np.array([[1, 2, 3, 4, 5],[2, 2, 3, 4…...

Linux·进程概念(上)

1.操作系统 任何计算机系统都包含一个基本的程序合集&#xff0c;称为操作系统(Operator System)。笼统的理解&#xff0c;操作系统包括&#xff1a; 内核(进程管理&#xff0c;内存管理&#xff0c;文件管理&#xff0c;驱动管理) 其他程序(函数库&#xff0c;shell程序) OS的…...