我有一个字符串列表。我想根据返回双精度的函数来评估每个字符串。然后我想要前 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来做。它让我发疯。
首先我尝试填充 a HashMap<String, Double>
,然后使用Collections.sort
自定义比较器,就像 Perl 版本一样。但是 Comparator 的作用域阻止了它引用 HashMap 来查找值。
然后我尝试了 a 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<String> strs = treemap.values();
ArrayList<String> a = new ArrayList<String>(strs);
return new ArrayList<String>(a.subList(0, 5));
最后,一些有效的东西!但是两个额外的数据结构只是为了获得前五个元素?而且我不太喜欢使用 Double 作为 TreeMap 的键。
有更好的解决方案吗?