什么时候用 ArrayList,什么时候用 HashSet?:

需求 ArrayList HashSet
需要有序
需要允许重复元素
快速查找元素是否存在 ❌ O(n) ✅ O(1)
需要去重 ❌ O(n²) ✅ O(n)
频繁增删元素 ❌ O(n)(删除慢) ✅ O(1)
遍历所有元素 ✅ 更快
哈希表

HashMap<K, V> 使用键值对存储数据:

  • 允许 null 作为键和值( Hashtable 不允许)。
  • 非线程安全,适用于单线程环境,如果要在多线程环境下使用,需要使用 Collections.synchronizedMap()ConcurrentHashMap
  • 基于哈希算法,查询效率很高(平均O(1)时间复杂度)。

示例:

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        // 创建 HashMap
        HashMap<String, Integer> map = new HashMap<>();

        // 添加键值对
        map.put("苹果", 10);
        map.put("香蕉", 5);
        map.put("橙子", 8);

        // 访问元素
        System.out.println("苹果的价格: " + map.get("苹果")); // 10

        // 遍历 HashMap
        for (String key : map.keySet()) {
            System.out.println(key + " 价格: " + map.get(key));
        }

        // 删除元素
        map.remove("香蕉");

        // 判断是否包含某个键或值
        System.out.println("是否包含 '苹果': " + map.containsKey("苹果")); // true
        System.out.println("是否包含 5: " + map.containsValue(5)); // false

        // 获取大小
        System.out.println("哈希表大小: " + map.size());
    }
}

Hashtable(线程安全,使用较少):

  • 不允许 null 作为键或值。
  • 线程安全(每个方法都用 synchronized 修饰)。
  • 由于 synchronized 影响性能,现在推荐使用 ConcurrentHashMap 代替 Hashtable

示例

import java.util.Hashtable;

public class Main {
    public static void main(String[] args) {
        // 创建 Hashtable
        Hashtable<String, Integer> table = new Hashtable<>();

        // 添加元素
        table.put("苹果", 10);
        table.put("香蕉", 5);
        table.put("橙子", 8);

        // 遍历 Hashtable
        for (String key : table.keySet()) {
            System.out.println(key + " 价格: " + table.get(key));
        }
    }
}

ConcurrentHashMap(适用于多线程)

多线程环境 下使用哈希表,推荐ConcurrentHashMap<K, V> ,它比 Hashtable 更高效:

import java.util.concurrent.ConcurrentHashMap;

public class Main {
    public static void main(String[] args) {
        // 创建 ConcurrentHashMap
        ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();

        // 添加元素
        concurrentMap.put("苹果", 10);
        concurrentMap.put("香蕉", 5);

        // 遍历
        concurrentMap.forEach((k, v) -> System.out.println(k + " 价格: " + v));
    }
}

总结:

  • HashMap:适用于 单线程环境,允许 null,效率高。
  • Hashtable:适用于 多线程,不允许 null,但性能较差。
  • ConcurrentHashMap:推荐用于 多线程环境,比 Hashtable 更高效。

多线程环境推荐 使用ConcurrentHashMap。单线程环境,使用 HashMap .

HashSet

特点:

  • 元素唯一
  • 无序存储(元素的顺序可能与插入顺序不同)。
  • 查询、插入、删除操作速度快(平均时间复杂度 O(1))。

基本使用

import java.util.HashSet;
import java.util.Iterator;

public class HashSetExample {
    public static void main(String[] args) {
        // 1. 创建 HashSet
        HashSet<String> set = new HashSet<>();

        // 2. 添加元素(不会存储重复元素)
        set.add("Apple");
        set.add("Banana");
        set.add("Orange");
        set.add("Apple"); // 重复元素不会被加入

        // 3. 判断是否包含某个元素
        System.out.println("包含 Apple? " + set.contains("Apple"));

        // 4. 删除元素
        set.remove("Banana");

        // 5. 获取集合大小
        System.out.println("集合大小: " + set.size());

        // 6. 遍历 HashSet(方式一:增强 for 循环)
        for (String fruit : set) {
            System.out.println(fruit);
        }

        // 7. 遍历 HashSet(方式二:迭代器)
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        // 8. 清空集合
        set.clear();
        System.out.println("集合是否为空? " + set.isEmpty());
    }
}

HashSet , TreeSet , LinkedHashSet 的区别:

集合类型 底层结构 是否有序 查询速度 适用场景
HashSet 哈希表(HashMap 无序 O(1) 需要快速查找
TreeSet 红黑树 有序(按大小排序) O(log n) 需要排序的集合
LinkedHashSet 哈希表 + 链表 插入顺序 O(1) 需要有序且快速查找
常用 Map 方法
方法 作用
V put(K key, V value) 添加或更新键值对
void putAll(Map<K,V> m) 批量添加键值对
V remove(K key) 删除指定键
int size() 获取 Map 中键值对数量
boolean isEmpty() 判断 Map 是否为空
boolean containsValue(V value) 判断 Map 是否包含某个值
Set<K> keySet() 获取所有
Collection<V> values() 获取所有
Set<Map.Entry<K,V>> entrySet() 获取所有 键值对
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐