Java 8 Sort HashMap,其中映射键是 <String, Integer> 的对象

标签 java collections hashmap type-conversion

我有一个像这样的简单客户类

public class Customer {
    public int age;
    public int discount;
    public String name;

    public Customer(String name) {
        this.name = name;
    }
    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Customer(String name, int age, int discount) {
        this.name = name;
        this.age = age;
        this.discount = discount;
    }

    @Override
    public String toString() {
        return "Customer [age=" + age + ", discount=" + discount + ", name=" + name + "]";
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Integer getDiscount() {
        return discount;
    }
    public void setDiscount(int discount) {
        this.discount = discount;
    }
}

我使用此填充这些对象的列表

List<Customer> customerList = new ArrayList<>(Arrays.asList(
        new Customer("John",   2, 15),
        new Customer("John",   4, 15),
        new Customer("John",   6, 25),
        new Customer("Joe",    3, 15),
        new Customer("Joe",    3, 15),
        new Customer("Joe",    3, 15),
        new Customer("Goerge", 6, 25),
        new Customer("Goerge", 6, 25),
        new Customer("Mary",   7, 25),
        new Customer("Jane",   1, 15),
        new Customer("Jane",   2, 15),
        new Customer("Jane",   8, 25),
        new Customer("Jane",   8, 25)
        ));

现在我想使用这样的收集器对名称和折扣进行分组和计数

Map<Object, Long> collected = customerList
    .stream()
    .collect(Collectors.groupingBy(x -> Arrays.asList(x.name, x.discount), Collectors.counting()));

我可以使用这个查看我的输出

collected.entrySet().forEach(c -> {
    System.out.println(c);
});

输出以下内容

[Jane, 15]=2
[Joe, 15]=3
[John, 15]=2
[Mary, 25]=1
[John, 25]=1
[Jane, 25]=2
[Goerge, 25]=2

问题是如何按名称和折扣对 map 进行排序,使其看起来像这样

[Goerge, 25]=2
[Jane, 15]=2
[Jane, 25]=2
[Joe, 15]=3
[John, 15]=2
[John, 25]=1
[Mary, 25]=1

我不断遇到收集器返回的对象类型?

我可以转换收集器以便它返回一个类,也许是类似的东西

private class DiscountCounts
{
    public String name;
    public Integer discount;
}

是否可以转换 Map<**Object**, Long>()类似 Map<DiscountCounts, Long>() ,这是否允许使用 lambda 或 Comparator 构造访问 Map 键的字段?

我尝试了类似的方法,迭代 map 并手动转换为我想要的 map ,但我无法获取原始集合的键?

    Map<DiscountCounts, Long> collected2 = new HashMap<>();
    collected.entrySet().forEach(o -> {
        DiscountCounts key1 = (DiscountCounts)o.getKey();  //--> Fails here
        collected2.put((DiscountCounts)o.getKey(), o.getValue());
    });

最佳答案

不使用 DiscountCounts 类的一种方法是,首先对列表进行排序,然后按操作进行摸索,并使用 LinkedHashMap 保存排序顺序

Map<List<Object>, Long> map = customerList.stream()
                .sorted(Comparator.comparing(Customer::getName).thenComparing(Customer::getDiscount))
                .collect(Collectors.groupingBy(x -> Arrays.asList(x.name, x.discount),LinkedHashMap::new, Collectors.counting()));

使用 DiscountCounts 类的另一种方法是,重写 DiscountCounts 类的 equalshashcode 并执行分组通过为每个 Customer 对象创建 DiscountCounts 对象作为 Map 中的键,并将 TreeMapComparator< 结合使用 对结果进行排序

Map<DiscountCounts, Long> result = customerList.stream().collect(Collectors.groupingBy(
            c -> new DiscountCounts(c.getName(), c.getDiscount()),
            () -> new TreeMap<DiscountCounts, Long>(
                    Comparator.comparing(DiscountCounts::getName).thenComparing(DiscountCounts::getDiscount)),
            Collectors.counting()));

@Andreas 在评论中建议启发我另一种方法,我认为这是您可以在 DiscountCounts 上实现 Comparable 并提供的最佳方法之一排序逻辑,这样您就不需要向 TreeMap 提供 Comparator

@Override
public int compareTo(DiscountCounts cust) {

      int last = this.getName().compareTo(cust.getName());

     return last == 0 ? this.getDiscount().compareTo(cust.getDiscount()) : last;
}

Map<DiscountCounts, Long> result1 = customerList.stream().collect(Collectors.groupingBy(
            c -> new DiscountCounts(c.getName(), c.getDiscount()), TreeMap::new, Collectors.counting()));

关于Java 8 Sort HashMap,其中映射键是 <String, Integer> 的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60733383/

相关文章:

java - 如何在 Tomcat 中安排任务

java - 具有弱键和身份哈希的 ConcurrentHashMap?

java - 如何在android中仅以编程方式创建日期文本编辑?

c# - 如何交叉两个不同的 IEnumerable 集合

java - 从此对象集合中获取 object.getSomething() 的集合

java - 如何在没有初始动画的情况下更新 ListView 内的 SpeedView?

performance - Scala Collection 排序、sortWith 和 sortBy 性能

java - 如何在不覆盖之前数据的情况下使用 hashmap.put? ( java )

Java - 映射键查找忽略大小写

R 整数键,值映射