【问题标题】:Sum of certain HashMap values in list only if there is a match in value under a different key仅当不同键下的值匹配时,列表中某些 HashMap 值的总和
【发布时间】:2019-04-10 09:15:22
【问题描述】:

我有一个 ArrayList,其中包含数千个 HashMap,其中四个键和值映射到它们,如下所示:

HashMap<String, Object> map = new HashMap<>();
map.put("ID", 1);
map.put("NAME", name);
map.put("WORK_TIME", workTime);
map.put("ACCOUNT", name);

现在有了这些 HashMap 的 ArrayList,我想总结具有相同 ID、姓名和帐户的人的工作时间,例如:

HashMap<String, Object> map1 = new HashMap<>();
map1.put("ID", 1);
map1.put("NAME", "Edward");
map1.put("WORK_TIME", 20);
map1.put("ACCOUNT", null);

HashMap<String, Object> map2 = new HashMap<>();
map2.put("ID", 1);
map2.put("NAME", "Krzych");
map2.put("WORK_TIME", 6);
map2.put("ACCOUNT", 123);

HashMap<String, Object> map3 = new HashMap<>();
map3.put("ID", 1);
map3.put("NAME", "Edward");
map3.put("WORK_TIME", 13.5);
map3.put("ACCOUNT", null);

HashMap<String, Object> map4 = new HashMap<>();
map4.put("ID", 2);
map4.put("NAME", "Grzesiek");
map4.put("WORK_TIME", 50);
map4.put("ACCOUNT", null);

HashMap<String, Object> map5 = new HashMap<>();
map5.put("ID", 2);
map5.put("NAME", "Edward");
map5.put("WORK_TIME", 12);
map5.put("ACCOUNT", 123);

[..]

ArrayList<HashMap<String,Object>> arrList = new ArrayList<>();
arrList.put..

结果我应该得到一个包含 4 个 HashMap 的 ArrayList,其中只有两个具有相同 ID 和帐户的 Edward HashMap 合并为一个,工作时间为 33.5。

我想出的唯一方法是遍历所有地图,比较这三个值,然后成功替换存储在第二个数组列表中的哈希图中的工作时间值 我正在使用 Java 8,我想使用流来完成此任务,这可能吗?或者你有没有更好的解决方案?

【问题讨论】:

  • 使用具体的类来执行这样的操作。例如class Employee { int id; String name;int workTime;Integer account;} 。此外,您可以收集这些 toMapname 作为键并相应地合并值。
  • 我同意所有给出的答案,但是,数据来自哪里?我的猜测是数据来自某种数据库,因此直接在数据库级别执行 GROUP BY 是明智的。
  • 是的,你是对的,所有的数据都来自数据库。谢谢你的建议,我试试看。

标签: java hashmap java-stream


【解决方案1】:

这个 lambda:

Map<String, List<HashMap<String, Object>>> xxx = arrList.stream().collect(Collectors.groupingBy(x -> ((int) x.get("ID") + "") + x.get("NAME")));

给出如下结果:

但是,就像上面提到的——你应该使用(如果可能的话)对象而不是数组。 使用对象 lambda 看起来像这样:

Map<String, List<Person>> xxx = arrList.stream().collect(Collectors.groupingBy(x -> x.getName() + x. getId()));

但由于您有 Person 类,您可以覆盖 equals 以满足您的需求,并且您可以在一个简单的 lambda 中映射和求和工作时间:

Map<Person, Double> result = arrList.stream().collect(Collectors.groupingBy(x -> x, Collectors.summingDouble(Person::getWorkTime)));

这是结果 - 以 Person 为键的映射,以工作时间摘要为值。

Person 类的代码:

public class Person {
        String name;
        int id;
        double workTime;

        public Person(String name, int id, double workTime) {
            this.name = name;
            this.id = id;
            this.workTime = workTime;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Person person = (Person) o;
            return id == person.id &&
                    Objects.equals(name, person.name);
        }

        @Override
        public int hashCode() {

            return Objects.hash(name, id);
        }
    }

示例代码:

Person person1 = new Person("Edward", 1, 20);
Person person2 = new Person("Krzych", 1, 6);
Person person3 = new Person("Edward", 1, 13.5);
Person person4 = new Person("Grzesiek", 2, 50);
Person person5 = new Person("Edward", 2, 12);

ArrayList<Person> arrList = new ArrayList<>();

arrList.add(person1);
arrList.add(person2);
arrList.add(person3);
arrList.add(person4);
arrList.add(person5);

Map<Person, Double> result = arrList.stream().collect(Collectors.groupingBy(x -> x, Collectors.summingDouble(Person::getWorkTime)));

【讨论】:

    猜你喜欢
    • 2020-09-06
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-12
    • 2016-01-28
    • 2021-12-29
    相关资源
    最近更新 更多