我有一个字符串列表。我想基于一个返回双精度浮点数的函数来评估每个字符串。然后,我想根据它们计算出的值,获取前5个字符串。如果少于5个,则按顺序获取所有字符串。假设这些字符串是化合物,函数计算它们的质量。该函数的计算成本很高;我需要对每个字符串仅评估一次。(这里只是举例子,数据是虚构的。)
H2O => 18.5
C12H11O22 => 109.1
HeNe => 32.0
H2SO4 => 54.37
HCl => 19.11
4FeO3 => 82.39
Xe6 => 281.9
该程序应该按其各自值的顺序返回前五个字符串。对于这个示例数据:
H20,HCl,HeNe,H2SO4,4FeO3
。 实际上,我并不关心顺序; 我只需要任意顺序的最低的五个。我思考了如何在Perl中完成这项任务。它只需要几行代码:
foreach $s (@str) {
$strmap{$s} = f($s);
}
@sorted = sort { $strmap{$a} <=> $strmap{$b} } keys %strmap;
return @sorted[0, 4]
但我需要用Java来实现,这真的让我感到疯狂。
首先我尝试通过填充一个 HashMap<String, Double>
,然后使用具有自定义比较器的 Collections.sort
来排序,就像Perl版本一样。但是,比较器上的作用域阻止它引用 HashMap 来查找值。
然后我尝试了一个 TreeMap<String, Double>
,但它只按键排序,无论如何强制都不能按值对条目进行排序。
所以我尝试了一个 TreeMap<Double, String>
。它会丢弃相同Double的条目。然而,映射到相同Double的字符串的可能性很低,所以我继续前进。将条目添加到 TreeMap 中没有问题,但是我在从中提取值时遇到了问题。
TreeMap 提供了一个名为 subMap
的方法,但其参数是限定子集的键。我不知道它们是什么;我只想要前五个。所以我尝试使用 values
方法将所有值从 TreeMap 中取出,希望它们按顺序排列。然后我可以只获取前十个。
ArrayList<String> strs = (ArrayList<String>)(treemap.values());
return new ArrayList<String>(strs.subList(0, 5));
不行。运行时错误:无法将TreeMap$Values转换为ArrayList。
List<String> strs = (List<String>)(treemap.values());
return new ArrayList<String>(strs.subList(0, 5));
一样。在尝试强制转换时发生运行时错误。好的,让我们将其分配给一个集合...
Collection<String> strs = treemap.values();
return new ArrayList<String>(strs.subList(0, 5));
抱歉,subList
不是 Collection 的一个方法。
Collection<String> strs = treemap.values();
ArrayList<String> a = new ArrayList<String>(strs);
return new ArrayList<String>(a.subList(0, 5));
终于有东西能用了!但是为了获取前五个元素需要两个额外的数据结构吗?我也不太喜欢使用Double作为TreeMap的键。
有更好的解决方案吗?