List<HashMap> Stream 多字段汉字排序

在最近一次项目开发中,需要对List< HashMap>做排序,在做的过程中,发现与 List<类>的编写方法不一样,记录一下。

首先说一下项目背景,需要做一个排行榜功能,排序字段rank1,rank2,rank1是bigdecimal类型数字,rank2是汉字。
需要做排序的是一个List< HashMap>,需要对rank1降序,rank2升序排序后并补充名次。

介绍下我的编写过程。

  1. 最一开始时,没注意还需要对rank2排序,就只对rank1做了排序,和List<类> 差不多
List<HashMap> collect = list.stream().sorted(Comparator.comparing(map -> MathUtils.getBigDecimal((Map)map.get(rank1)),Comparator.reverseOrder()))
                .collect(Collectors.toList());

List<类>的

List<> collect = list.stream().sorted(Comparator.comparing(::属性一).reversed()).collect(Collectors.toList());

// 或者
List<> collect = list.stream().sorted(Comparator.comparing(::属性一,Comparator.reverseOrder())).collect(Collectors.toList());

  1. 发现还需要对第二个字段做排序后,很自然地想到在后面直接加 thenComparing
// 注意,这里会报错
// 如果是 List<类> 是可以直接加的
List<HashMap> collect = list.stream().sorted(Comparator.comparing(map -> MathUtils.getBigDecimal((Map)map.get(rank1)),Comparator.reverseOrder()).thenComparing(map -> map.get(rank2).toString())).collect(Collectors.toList());

报错如下
提示报错
3. 既然放在一块时,hashmap读取出错,那就分开写试试,问题解决

// 对rank1降序
Comparator<HashMap> comparatorRank1 = Comparator.comparing( map -> MathUtils.getBigDecimal( map.get(rank1)), Comparator.reverseOrder());
// 对rank2升序
Comparator<HashMap> comparatorRank2 = Comparator.comparing( map -> map.get(rank2).toString());
// 对List排序
list.sort(comparatorRank1.thenComparing(comparatorRank2));
  1. 新的问题,要求的是对rank2按首字母升序排序,由于rank2 是汉字,直接排序会失败(不报错)。需要指定一下 语言环境。
// 排序
        Comparator<HashMap> comparatorRank1 = Comparator.comparing( map -> MathUtils.getBigDecimal( map.get(rank1)), Comparator.reverseOrder());
        // 指定语言环境为中文
        Collator collator = Collator.getInstance(java.util.Locale.CHINA);
        Comparator<HashMap> comparatorRank2 = Comparator.comparing( map -> map.get(rank2).toString(),collator);

        list.sort(comparatorRank1.thenComparing(comparatorRank2));

到此排序完成。

Life is fantastic

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用Java8的Stream API来实现这个共通方法。具体实现如下: ``` public static <A, B> Map<List<Object>, List<Object>> match(List<A> listA, Function<A, List<Object>> keyExtractorA, List<B> listB, Function<B, List<Object>> keyExtractorB) { Map<List<Object>, List<Object>> result = new HashMap<>(); Map<List<Object>, List<A>> mapA = listA.stream().collect(Collectors.groupingBy(keyExtractorA)); Map<List<Object>, List<B>> mapB = listB.stream().collect(Collectors.groupingBy(keyExtractorB)); for (Map.Entry<List<Object>, List<A>> entryA : mapA.entrySet()) { List<Object> key = entryA.getKey(); List<B> matchListB = mapB.get(key); if (matchListB != null) { List<Object> valueA = entryA.getValue().stream().map(a -> (Object) a).collect(Collectors.toList()); List<Object> valueB = matchListB.stream().map(b -> (Object) b).collect(Collectors.toList()); result.put(key, valueB); } } return result; } ``` 该方法接受两个List,分别是List<A>和List<B>,以及两个Function对象,分别用于从A和B对象中提取用于匹配的多个字段。该方法返回一个Map,其中key是匹配成功的字段列表,value是匹配成功的List<B>对象。 该方法的实现分为以下几个步骤: 1. 对List<A>和List<B>分别使用Stream API进行分组,分组依据是从A和B对象中提取的多个字段。 2. 遍历List<A>的分组结果,对于每个分组,从List<B>的分组结果中查找是否存在相同的分组。 3. 如果存在相同的分组,则将List<A>和List<B>中的对象分别转换成Object类型的List,并放入结果Map中。 使用该方法的示例代码如下: ``` List<Person> listA = Arrays.asList(new Person("Alice", 20), new Person("Bob", 25), new Person("Charlie", 30)); List<Animal> listB = Arrays.asList(new Animal("Alice", 2), new Animal("Bob", 3), new Animal("Dave", 4)); Map<List<Object>, List<Object>> result = match(listA, p -> Arrays.asList(p.getName(), p.getAge()), listB, a -> Arrays.asList(a.getName(), a.getAge())); result.forEach((key, value) -> System.out.println(key + " -> " + value)); ``` 该示例代码中,List<Person>和List<Animal>分别表示人和动物的列表,两个列表中的对象都有名字和年龄两个字段,我们使用match方法来将两个列表中名字和年龄相同的对象进行匹配。匹配结果输出如下: ``` [Alice, 20] -> [Alice, 2] [Bob, 25] -> [Bob, 3] ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值