【问题标题】:HashMap/TreeMap sorting my keysHashMap/TreeMap 对我的键进行排序
【发布时间】:2014-05-25 20:31:52
【问题描述】:

我正在使用 JSoup 从一个提供花粉数据的网站上抓取一些数据。他们没有 API 访问权限,所以抓取是我最后的手段。

使用HashMap,我存储datepollenIndex,这是当天花粉水平在0.0 - 10.0 范围内的水平。

private static Map<String, String> pollenMap = new HashMap<String, String>();

这是我的Pollen 类的构造函数的一部分。

for(int i = 0; i < 4; i++)
{
    Element dates = doc.select("td.text-center.even-four").get(i);
    Element levels = doc.select("td.levels").get(i);

    System.out.println(dates.text() + ", " + levels.text());

    pollenMap.put(dates.text(), levels.text());
}

一个问题是HashMap 为我排序数据。 pollenMap 的输出是这样的:

 : [Monday May 26, 2014, Wednesday May 28, 2014, Sunday May 25, 2014, Tuesday May 27, 2014]
 : [7.90, 6.60, 7.60, 8.80]

如您所见,HashMap 对我的 dates 键进行排序,导致 Monday 排在第一位,Tuesday 排在最后。

我可能错误地使用了HashMap,所以我的朋友建议我使用TreeMap,然而,结果是这样的:

 : [Monday May 26, 2014, Wednesday May 28, 2014, Sunday May 25, 2014, Tuesday May 27, 2014]
 : [7.90, 6.60, 7.60, 8.80]

如何在不排序的情况下使用这个键值结构?

对于这个数据结构的新手问题,我们深表歉意。我可以使用两个String 列表,但我想学习这些新的数据结构。

【问题讨论】:

  • 哦,对不起。这是否意味着我错误地使用了HashMap
  • 顺序变了是不是有问题?或者它只是让你感到惊讶?通常,当您需要键值映射时,键值对的顺序并不重要。
  • TreeMap 上的迭代顺序取决于用作键的对象的类型。您还可以提供自定义Comparator 来影响订单。我的猜测是,您的问题源于您用作键的字符串的格式以及缺乏能够按照您想要的方式比较它们的合理函数。您最好将字符串解析为日期并使用日期作为键。
  • 在问这样一个微不足道的问题之前,值得先阅读 Java 文档并检查有关正在使用的数据结构的基本信息。 -1
  • @OlegS。在我看来,这与数据结构无关,而是用作输入的错误数据类型。我使用了String,但正确的方法是Date。我现在使用Date 而不是String

标签: java data-structures hashmap treemap


【解决方案1】:

(1) java.util.HashMap 不保证订单。

(2)java.util.SortedMap,如java.util.TreeMap按key排序。 (在您的情况下,按字典顺序对 String 键进行排序。)


如何在不排序的情况下使用这个键值结构?

如果您想按照插入顺序迭代键值对,则需要java.util.LinkedHashMap

此实现与 HashMap 的不同之处在于,它维护一个双向链表,贯穿其所有条目。该链表定义了迭代顺序,通常是键插入映射的顺序(插入顺序)。


OP 不想保留插入顺序。他/她想要约会顺序。

如果您想按日期顺序迭代键值,请使用java.util.TreeMap,但parse Strings 到Dates。

SimpleDateFormat format = new SimpleDateFormat("EEEEE MMMM d, yyyy");
for(int i = 0; i < 4; i++)
{
    Element dates = doc.select("td.text-center.even-four").get(i);
    Element levels = doc.select("td.levels").get(i);

    System.out.println(dates.text() + ", " + levels.text());

    pollenMap.put(format.parse(dates.text()), levels.text());
}

顺便说一句,您可能希望对测量值执行相同的操作,并将它们存储为 longs 或 java.math.BigDecimals。

【讨论】:

  • +1 表示 LinkedHashMap。这是“按要求”对这个问题的正确答案,即使我认为这不是 OP 想要的。
  • 嗨,保罗。我已经实现了自己的 SimpleDateFormat 解析器。我没有使用你的,但它最终看起来和我们试图实现的目标一样。我的问题是,我的日期解析器自己也添加了HH:mm:ss,例如:Sun May 25 00:00:00 EDT 2014。为什么要这样做?
  • @theGreenCabbage,Java 中的Date 实际上是一个日期和时间。默认情况下,当您在其上调用toString() 时,会包括时间。如果您不希望String 表示中的时间,您可以使用相同的DateFormat,然后执行format.format(myDate)。 (仅供参考,如果您碰巧不喜欢 Java 7 的日期 API,您可能会喜欢 Java 8 带来的一些改进。)
  • 您解释的内容是否仅适用于get 进程?如您所说,添加Date 对象实际上是一个日期和时间。
【解决方案2】:

HashMap 不对数据进行排序;它散列键以将数据分配给存储桶!您可以创建 Key-Value 类型并将数据存储在 ListStack 中。他们将保留您的广告订单。

【讨论】:

  • @PaulDraper TreeMap 确实对键进行了排序。 OP 希望保留插入顺序。 如何在不排序的情况下使用这个键值结构?
  • 不,OP 不想保留插入顺序。他/她想要约会顺序。
  • 谢谢大卫,这就是我想要的。
【解决方案3】:

您的问题是您使用String 值来存储日期和小数。当您进行排序时,您的日期会按字母顺序排序,在本例中是将星期一放在星期六之前,依此类推。

由于您在地图中存储日期数据和十进制数据,因此您应该将其设为TreeMap&lt;Date,BigDecimal&gt; 而不是TreeMap&lt;String,String&gt;。在将它们放入地图之前解析您的日期和小数。然后TreeMap 代码将对它们进行正确排序。

【讨论】:

  • OP:“如何在不排序的情况下使用这个键值结构?”一开始我和你一样误读了。
  • 不,@PaulDraper,他/她的意思是不要按字母顺序重新排列日期。我不相信我误解了这一点。但也许 OP 可以澄清一下。
  • 从 OP 对 Elliott 的回答的 cmets 看来,日期顺序确实是想要的,而不是“没有排序”。伟大的读心术:P
猜你喜欢
  • 1970-01-01
  • 2018-06-06
  • 2013-11-03
  • 1970-01-01
  • 1970-01-01
  • 2017-09-22
  • 2022-12-09
  • 2016-08-19
  • 2015-04-22
相关资源
最近更新 更多