TreeMap和HashMap的问题

本文介绍了如何通过自定义Key类的hashCode方法,将HashMap的数据组织为TreeMap形式,实现数据的先进先出特性。通过实例代码演示了Key类的创建与使用,并分析了其限制及可能的优化方向。

    在一次面试的过程中,有一个问题“HashMap存放数据是无序的,如何编写程序,使数据先进先出。”当时我没做出来,但是我回来折腾了半天,就写了下面的成序。
     首先思考HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,然后在google下,通过改变key的hashCode的值来实现。程序如下:

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author Admini
*/
public class TreeTest extends HashMap {

    public static void main(String[] ages) {

        TreeTest t = new TreeTest();
      
        t.put(new Key(1), "a");
        t.put(new Key(2), "b");
        t.put(new Key(3), "c");
        t.put(new Key(4), "d");
        t.put(new Key(5), "e");
        t.put(new Key(6), "f");
        t.put(new Key(7), "h");
        t.put(new Key(8), "i");
        t.put(new Key(2), "y");
        Set s = t.keySet();
        Iterator f = s.iterator();

        while (f.hasNext()) {
            Key ts = (Key) f.next();
            System.out.println(ts + " = " + t.get(ts));
        }
    }
}

/**
*创建Key类,作为Map的Key
*/
class Key {

    int number = 0;

    public Key(int s) {
        number = s;
    }

    public int hashCode() {
        return number;
    }

    public boolean equals(Object o) {
        return (o instanceof Key) && (number == ((Key) o).number);
    }

    public String toString() {
        return String.valueOf(number);
    }
}
   通过创建new Key(Integer t)作为Map中的key,key的hashCode是Key类的的构造方法number指定。但是这种方式还是有它的限制,是不是有更好的方法实现呢?还有TreeMap是可以达到先进先出的.

<think>我们被要求解释TreeMapHashMap,并提供代码示例。 首先,我们将分别介绍TreeMapHashMap,然后比较它们的区别,最后提供一些代码示例。 </think>### TreeMapHashMap 详解 在 Java 中,`TreeMap` `HashMap` 都是实现了 `Map` 接口的关键集合类,但它们在底层实现、性能特性使用场景上有显著差异。以下是详细对比: #### 1. HashMap - **底层实现**:哈希表(数组 + 链表/红黑树) - **排序**:无序(迭代顺序不确定) - **空值**:允许一个 null 键多个 null 值 - **时间复杂度**: - 平均情况:O(1) 的 get/put 操作 - 最坏情况:O(n)(哈希冲突严重时) - **线程安全**:非线程安全(需用 `Collections.synchronizedMap`) - **适用场景**:需要快速查找/插入,不关心顺序的场景 ```java import java.util.HashMap; import java.util.Map; public class HashMapExample { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(); // 添加元素 hashMap.put("Apple", 10); hashMap.put("Banana", 5); hashMap.put(null, 3); // 允许null键 hashMap.put("Orange", null); // 允许null值 // 获取元素 System.out.println("Apple count: " + hashMap.get("Apple")); // 输出: Apple count: 10 // 遍历(无序) System.out.println("\nHashMap iteration:"); hashMap.forEach((k, v) -> System.out.println(k + " => " + v)); // 可能输出(顺序不确定): // null => 3 // Apple => 10 // Orange => null // Banana => 5 } } ``` #### 2. TreeMap - **底层实现**:红黑树(自平衡二叉搜索树) - **排序**:按键的自然顺序或自定义比较器排序 - **空值**:不允许 null 键(但允许 null 值) - **时间复杂度**: - 所有操作:O(log n) - **线程安全**:非线程安全 - **适用场景**:需要按键排序的场景(如范围查询) ```java import java.util.TreeMap; import java.util.Map; public class TreeMapExample { public static void main(String[] args) { Map<String, Integer> treeMap = new TreeMap<>(); // 添加元素(自动排序) treeMap.put("Apple", 10); treeMap.put("Banana", 5); treeMap.put("Orange", 8); // treeMap.put(null, 3); // 抛出NullPointerException // 范围查询 System.out.println("HeadMap (A-C): " + ((TreeMap<String, Integer>) treeMap).headMap("C")); // 输出: {Apple=10, Banana=5} // 遍历(按键排序) System.out.println("\nTreeMap iteration:"); treeMap.forEach((k, v) -> System.out.println(k + " => " + v)); // 输出(按字母顺序): // Apple => 10 // Banana => 5 // Orange => 8 } } ``` ### 核心对比表 | 特性 | HashMap | TreeMap | |---------------------|--------------------------|--------------------------| | **底层数据结构** | 哈希表 | 红黑树 | | **排序** | 无序 | 按键自然排序 | | **null 键** | 允许 | 不允许 | | **null 值** | 允许 | 允许 | | **时间复杂度** | O(1) 平均,O(n) 最坏 | O(log n) | | **内存占用** | 较低(无排序开销) | 较高(树结构开销) | | **特殊操作** | - | 支持范围查询(firstKey, subMap等) | | **最佳场景** | 高频插入/查询,无需排序 | 需要有序遍历或范围查询 | ### 高级用法示例:自定义排序 ```java import java.util.Comparator; import java.util.TreeMap; public class CustomSortTreeMap { public static void main(String[] args) { // 按字符串长度排序 TreeMap<String, Integer> customMap = new TreeMap<>( Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder()) ); customMap.put("Apple", 10); customMap.put("Fig", 2); customMap.put("Banana", 7); customMap.forEach((k, v) -> System.out.println(k + " => " + v)); // 输出: // Fig => 2 // Apple => 10 // Banana => 7 } } ``` ### 性能优化建议 1. **HashMap**: - 初始化时设置合理容量:`new HashMap<>(expectedSize)` - 高冲突场景使用:`new HashMap<>(16, 0.75f)` 调整负载因子 2. **TreeMap**: - 自定义比较器避免不必要的排序开销 - 范围查询优先使用 `subMap()` 而非全量遍历 ### 何时选择? - 选 **HashMap** 当: - 需要最高效的 O(1) 访问 - 数据无需特定顺序 - 允许 null 键值 - 选 **TreeMap** 当: - 需要按键排序的迭代 - 需要范围查询(如找 A-C 开头的键) - 接受 O(log n) 的操作开销
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值