【问题标题】:Putting data in TreeMap, causing duplicate entries将数据放入TreeMap,导致重复条目
【发布时间】:2015-03-09 22:43:15
【问题描述】:

我在 Stackoverflow 上的第一篇文章,如果我发错了,请见谅...

所以我有一个带有大量个人数据的ArrayList<Person>(通过 json 从服务中获取,解析并映射到 POJO 人员)。 我想从这些数据中玩一些统计数据(绘制体重减轻/增加等图表)。

首先我插入所有人员标识符(从 HashSet 中的 ArrayList 中过滤掉重复项,为每个人留下唯一标识符。

然后我想要这个结构:

HashMap<String, TreeMap<Date, Double> mapWithWeightPerPerson = new HashMap<>();

所以我要做的是添加一个人的体重数据,每个日期使用 HashMap 中的 TreeMap。 (如果这是一个好的设计决策,可能需要讨论)。

因此,对于每个标识符,我都会遍历所有 Person 的 ArrayList 并将人员记录添加到 TreeMap 有一个键:日期(稍后可能会使用字符串)和一个值:权重的双倍。 然后我将 TreeMap 添加到外部 HashMap 并为所有标识符执行此操作。

for (String identifier : setWithUniqueIdentifiers) {
    TreeMap<Date, Double> personWeightData = new TreeMap<>();
    for (Person person : listWithAlotOfPersons) {
        if (person.getSymbol().equalsIgnoreCase(identifier)) {
            System.out.println("Date = " + person.getDate());
            System.out.println("Weight = " + person.getWeight());

            personWeightData.put(person.getDate(), person.getWeight()));
            for (Double weight : personWeightData.values()) {
                System.out.println("Values inserted so far: " + weight);
            }
        }
    }
    System.out.println("in key: " + identifier);
    mapWithWeightPerPerson.put(identifier, personWeightData);
}

在遍历 mapWithWeightPerPerson 并打印日期的所有人体重数据时,我一遍又一遍地得到理智的数据,即使我这样做了 personWeightData = new TreeMap();以上。这就是我打印 mapWithWeightPerPerson 时的样子。

Date = 2015-03-05
Weight = 44.16
Values inserted so far: 44.16
Date = 2015-03-04
Weight = 43.99
Values inserted so far: 43.99
Values inserted so far: 44.16
Date = 2015-03-03
Weight = 42.62
Values inserted so far: 42.62
Values inserted so far: 43.99
Values inserted so far: 44.16
Date = 2015-03-02
Weight = 44.11
Values inserted so far: 44.11
Values inserted so far: 42.62
Values inserted so far: 43.99
Values inserted so far: 44.16
Date = 2015-02-27
Weight = 44.28
Values inserted so far: 44.28
Values inserted so far: 44.11
Values inserted so far: 42.62
Values inserted so far: 43.99
Values inserted so far: 44.16
in key: FatBob
Date = 2015-03-05
Weight = 12.77
Values inserted so far: 12.77
Date = 2015-03-04
Weight = 12.82
Values inserted so far: 12.82
Values inserted so far: 12.77
Date = 2015-03-03
Weight = 12.76
Values inserted so far: 12.76
Values inserted so far: 12.82
Values inserted so far: 12.77
Date = 2015-03-02
Weight = 12.91
Values inserted so far: 12.91
Values inserted so far: 12.76
Values inserted so far: 12.82
Values inserted so far: 12.77
Date = 2015-02-27
Weight = 12.93
Values inserted so far: 12.93
Values inserted so far: 12.91
Values inserted so far: 12.76
Values inserted so far: 12.82
Values inserted so far: 12.77
in key: SkinnyPete
Date = 2015-03-05
Weight = 360.30
Values inserted so far: 360.3
Date = 2015-03-04
Weight = 360.50
Values inserted so far: 360.5
Values inserted so far: 360.3
Date = 2015-03-03
Weight = 360.40
Values inserted so far: 360.4
Values inserted so far: 360.5
Values inserted so far: 360.3
Date = 2015-03-02
Weight = 365.40
Values inserted so far: 365.4
Values inserted so far: 360.4
Values inserted so far: 360.5
Values inserted so far: 360.3
Date = 2015-02-27
Weight = 363.80
Values inserted so far: 363.8
Values inserted so far: 365.4
Values inserted so far: 360.4
Values inserted so far: 360.5
Values inserted so far: 360.3
in key: BaldJohn

但是在循环和打印 mapWithWeightPerPerson 时,我希望它是:

Person: FatBob
{2015-02-27=144.28, 2015-03-02=144.11, 2015-03-03=142.62, 2015-03-04=143.99, 2015-03-05=144.16}
Person: SkinnyPete
{2015-02-27=112.93, 2015-03-02=112.91, 2015-03-03=112.76, 2015-03-04=112.82, 2015-03-05=112.77}
Person: BaldJohn
{2015-02-27=363.8, 2015-03-02=365.4, 2015-03-03=360.4, 2015-03-04=360.5, 2015-03-05=360.3}

期待您的回答。

【问题讨论】:

  • 什么是 setWithUniqueQuoteNames?
  • 有些东西你没有向我们展示......对于初学者来说,你为什么不添加一个打印语句来指示你为每次迭代添加到地图中的条目(即,而不是在后端,在添加时打印)。这可能会告诉你有些事情是不对的。附带讨论:您概述的方法将起作用,但效率很低。最好循环一次数据并创建 personWeightData 对象(如果它不存在),然后将数据添加到 personWeightData(现有的或新创建的)。
  • @KevinDay 为了保持代码可读性,我删除了打印语句。我会尽快添加更多输出。
  • 在这三个中看起来像是同一个 TreeMap。用TreeMap&lt;Date, Double&gt; personWeightData = new TreeMap&lt;&gt;(); 代替personWeightData = new TreeMap&lt;&gt;(); 怎么样?
  • 您的代码似乎正确。您如何打印 mapWithWeightPerPerson 以及现在的结果是什么?

标签: java arraylist hashmap immutability treemap


【解决方案1】:

对于 mapWithWeightPerPerson 中的所有条目,您得到了相同的结果,所以问题可能是,

  1. TreeMap 实例在所有条目中都是相同的。
  2. 您将所有人员数据添加到每个 TreeMap 中

要验证它是否是由第一个原因引起的,您可以迭代 mapWithWeightPerPerson 并注销值的原始哈希,如果它们不同,则不是原因。

for (Map.Entry<String, TreeMap<Date, Double> entry : mapWithWeightPerPerson>) {
    System.out.println(System.identityHashCode(entry.getValue()));
}

要验证是否是由第二个原因引起的,可以在下面一行添加调试日志,

if (person.getName().equalsIgnoreCase(identifier)) {
    System.out.println(String.format("identifier %s, person name %s", identifier, person.getname()));
    personWeightData.put(person.getDate(), person.getWeight());
}

如果每个标识符有多个日志,则if子句中的条件错误。

【讨论】:

  • 1: System.out.println(System.identityHashCode(entry.getValue()));返回:1874154700 1632392469 2008362258 2:System.out.println(String.format("标识符%s,人名%s",标识符,person.getname()));给出:标识符 FatBob,人名 FatBob 标识符 BaldJohn,人名 BaldJohn 标识符 SkinnyPete,人名 SkinnyPete
【解决方案2】:

在我打印 mapWithWeightPerPerson (HashMap) 时出错:

for (Object o : mapWithWeightPerPerson.keySet()) {
    System.out.println("Person: " + o);
    Collection collection = mapWithWeightPerPerson.values();
    Iterator iterator = collection.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}

当改为:

Iterator it = mapWithWeightPerPerson.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry pair = (Map.Entry) it.next();
    System.out.println(pair.getKey() + " = " + pair.getValue());
    it.remove(); // avoids a ConcurrentModificationException
}

它适用于输出:

FatBob = {2015-02-27=44.28, 2015-03-02=44.11, 2015-03-03=42.62, 2015-03-04=43.99, 2015-03-05=44.16}
SkinnyPete = {2015-02-27=12.93, 2015-03-02=12.91, 2015-03-03=12.76, 2015-03-04=12.82, 2015-03-05=12.77}
BaldJohn = {2015-02-27=363.8, 2015-03-02=365.4, 2015-03-03=360.4, 2015-03-04=360.5, 2015-03-05=360.3}

【讨论】:

    猜你喜欢
    • 2012-07-30
    • 1970-01-01
    • 2020-04-01
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 2021-01-21
    • 2019-04-17
    相关资源
    最近更新 更多