You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据自定义类的String成员变量对HashMap进行排序

问题描述

我有一个类型为Map<Integer, CustomClass>的HashMap,CustomClass定义如下:

class CustomClass {
    String s;
    Integer i;
    // 构造方法、getter和setter
}

已完成Map的初始化并填充数据:

Map<Integer, CustomClass> map = new HashMap<>();

我需要根据CustomClass的String类型成员s对这个HashMap排序,尝试用Lambda表达式没得到正确的有序Map,还写了以下模拟代码:

import java.util.*;

class FileMap implements Comparable<FileMap> {
    private String fileName;
    private int file;

    public FileMap(String fileName, int file) {
        this.fileName = fileName;
        this.file = file;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public int getFile() {
        return file;
    }

    public void setFile(int file) {
        this.file = file;
    }

    @Override
    public int compareTo(FileMap that) {
        return this.fileName.compareTo(that.getFileName());
    }

    @Override
    public String toString() {
        return this.fileName;
    }
}

class Main {
    public static void main(String[] args) {
        FileMap fm1 = new FileMap("abc.txt", 0);
        FileMap fm2 = new FileMap("abd.txt", 0);
        FileMap fm3 = new FileMap("abe.txt", 0);
        FileMap fm4 = new FileMap("abf.txt", 0);
        Map<Integer, FileMap> fileMap = new HashMap<>();
        fileMap.put(0, fm1);
        fileMap.put(1, fm3);
        fileMap.put(2, fm2);
        fileMap.put(3, fm4);
        System.out.println(fileMap);

        Map<Integer, FileMap> tree = new TreeMap<>();
        tree.putAll(fileMap);
        System.out.println(tree);
    }
}

但问题仍未解决,求正确实现方法。

解决方案

你当前代码的核心问题:TreeMap默认是按**键(Key)**排序的,和值的Comparable实现完全无关。你的键是Integer类型,所以TreeMap只会按整数顺序输出,自然达不到按fileName排序的目的。

下面是两种可行的实现方式:

方法1:将Entry转为List后排序,再存入有序Map

把HashMap的键值对提取到List,用自定义规则排序后,存入LinkedHashMap保持顺序:

// 提取所有键值对到List
List<Map.Entry<Integer, CustomClass>> entryList = new ArrayList<>(map.entrySet());

// 按CustomClass的s字段升序排序
entryList.sort((entry1, entry2) -> {
    String s1 = entry1.getValue().getS();
    String s2 = entry2.getValue().getS();
    return s1.compareTo(s2); // 降序则改为s2.compareTo(s1)
});

// 存入LinkedHashMap保留排序结果
Map<Integer, CustomClass> sortedMap = new LinkedHashMap<>();
for (Map.Entry<Integer, CustomClass> entry : entryList) {
    sortedMap.put(entry.getKey(), entry.getValue());
}

// 验证输出
sortedMap.forEach((k, v) -> System.out.println(k + ": " + v.getS()));

对应你的模拟代码,修改Main方法如下:

public static void main(String[] args) {
    FileMap fm1 = new FileMap("abc.txt", 0);
    FileMap fm2 = new FileMap("abd.txt", 0);
    FileMap fm3 = new FileMap("abe.txt", 0);
    FileMap fm4 = new FileMap("abf.txt", 0);
    Map<Integer, FileMap> fileMap = new HashMap<>();
    fileMap.put(0, fm1);
    fileMap.put(1, fm3);
    fileMap.put(2, fm2);
    fileMap.put(3, fm4);
    System.out.println("原HashMap:" + fileMap);

    // 排序逻辑
    List<Map.Entry<Integer, FileMap>> entryList = new ArrayList<>(fileMap.entrySet());
    entryList.sort((e1, e2) -> e1.getValue().getFileName().compareTo(e2.getValue().getFileName()));

    Map<Integer, FileMap> sortedMap = new LinkedHashMap<>();
    entryList.forEach(entry -> sortedMap.put(entry.getKey(), entry.getValue()));

    System.out.println("按fileName排序后的Map:" + sortedMap);
}

方法2:用Stream API简化操作

Java 8+的Stream可以更简洁地完成排序和收集:

Map<Integer, CustomClass> sortedMap = map.entrySet()
    .stream()
    .sorted(Map.Entry.comparingByValue((v1, v2) -> v1.getS().compareTo(v2.getS())))
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        Map.Entry::getValue,
        (oldVal, newVal) -> oldVal, // 键冲突时保留旧值
        LinkedHashMap::new // 指定用LinkedHashMap保持顺序
    ));

对应模拟代码的Stream版本:

Map<Integer, FileMap> sortedMap = fileMap.entrySet()
    .stream()
    .sorted(Map.Entry.comparingByValue(Comparator.comparing(FileMap::getFileName)))
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        Map.Entry::getValue,
        (o, n) -> o,
        LinkedHashMap::new
    ));

注意事项

  • 不要试图用TreeMap实现按值排序,它的核心逻辑是按键排序,强行修改会导致键的比较逻辑混乱,甚至出现键覆盖问题。
  • 如果CustomClass的s字段可能为null,要在Comparator中处理空指针,比如:
    entryList.sort((e1, e2) -> {
        String s1 = e1.getValue().getS();
        String s2 = e2.getValue().getS();
        if (s1 == null) return s2 == null ? 0 : -1;
        if (s2 == null) return 1;
        return s1.compareTo(s2);
    });
    

内容的提问来源于stack exchange,提问作者Bhupesh Patil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 23:35:20