此方法采用一个所有值都等于null的映射,并返回一个由相同键组成的SortedMap和新值(通过objectiveFitness获得)
步骤1.首先,我从输入映射中提取键并用相同的键构造一个新的HashMap,新的值是objectiveFitness(key)。
public SortedMap<Integer[], Integer> evaluate(Map<Integer[], Integer> population, Integer[] melody, Integer[] mode) {
Map<Integer[], Integer> fitPop = new HashMap<>();
fitPop = population.keySet() //you just have the keys.
.stream()
.collect(Collectors.toMap(p -> p, p -> this.objectiveFitness(p)));
第二步。下一步是使用流将HashMap中的所有条目收集到带有自定义比较器的SortedMap中。
...我发现,由于我想根据条目的自然排序以外的东西来维护SortedMap的排序性,我需要实现一个包含两个部分的比较器。我将根据适合度值排序,使用键来比较唯一性。*另外,我想要两个值可以相似的情况,但我不想
一部分与排序有关,并根据值返回(1,0或-1)。比较器的另一部分与唯一性有关(因为地图不允许重复。这是我目前为止最好的一张照片,但我很挣扎。
Comparator<Map.Entry<Integer[], Integer>> fitnessOrder =
new Comparator<Map.Entry<Integer[], Integer>>() {
public int compare(Map.Entry<Integer[], Integer> m1, Map.Entry<Integer[], Integer> m2) {
int fitCmp = m2.getValue().compareTo(m1.getValue());
if (fitCmp != 0)
return fitCmp;
if(m1.getKey().equals(m2.getKey())) return 0;
for(int i = 0; i < m1.getKey().length; i++){
if(m1.getKey()[i] > m2.getKey()[i]){
return 1;
}
if(m1.getKey()[i] < m2.getKey()[i]){
return -1;
}
}
return 0;
}
};
这看起来和Equals一致吗?我真的说不出该如何实施。
SortedMap<Integer[], Integer> sortedFitPop = fitPop.entrySet()
.stream()
//now I want to insert entries into the TreeMap
//with sortedness according to the Comparator above
.collect(Collectors.toCollection((k,v) -> (k,v), new TreeMap(fitnessOrder)
));
键应该仍然是键,值应该仍然是它们在HashMap中的值,但是现在在收集时,我希望TreeMap应该始终从一开始和在每个条目被放入之后进行排序。
&是的,当然,最好不要收集到一个HashMap中开始,我觉得有一种方法可以使用Java-8/Streams/lambdas来干净利落地完成这件事。
提前谢谢!我很想知道这些东西!
正如Flown已经说过的,创建按值排序的treemap
是不可能的。考虑一下.当地图需要查找的结果来确定它在地图中的位置时,该如何实现查找?只有当所有的地图操作退化为整个地图的线性搜索或更糟时,这才会起作用。
另一个问题您已经提到过:与equals
的一致性。使用映射值的比较器不能与键的equals
一致,但即使是专用于integer[]
键的比较器也不能与equals
一致,因为Java数组没有equals
方法。在使用LinkedHashMap
和插入前按值排序时,这也会使您感到震惊。在这种情况下,查找将只用于相同的数组对象实例,而不是等效的元素序列,因为数组没有适当的hashcode
或equals
实现。
这是考虑无论如何都不应该使用integer[]
数组的一点。泛型不支持基元类型,但基元类型的数组不是基元类型,这可能会使您感到困惑。所以这里没有理由不使用int[]
。
使用int[]
数组时,可以使用intbuffer
包装它们,从而获得一个基于int[]
的内容一致地实现comparable
、hashcode
和equals
的类型。然后,可以从排序的流创建LinkedHashMap
。它将反映流元素的遇到顺序,这将是所需的顺序,只要您以后不修改映射。
// convert int[] arrays to IntBuffer via IntBuffer.wrap first
public Map<IntBuffer, Integer> evaluate(Map<IntBuffer, Integer> population, …) {
Map<IntBuffer, Integer> fitPop = population.keySet().stream()
.map(ia -> new AbstractMap.SimpleImmutableEntry<>(ia, objectiveFitness(ia.array())))
.sorted(Map.Entry.<IntBuffer,Integer>comparingByValue()
.thenComparing(Map.Entry.comparingByKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(a,b)->{ throw new IllegalStateException(); }, LinkedHashMap::new));
return fitPop;
}
看到这里,您可能会考虑从整数数组到整数的映射是否真的是一个总体的适当表示。当您为持有身份标准和当前适合度的人口成员创建专用类型时,您可以消除所有这些障碍。这些总体成员的简单列表或数组就足以表示一个总体。重新计算适应度将是一个简单的foreach
操作,并且根据适应度属性对列表或数组进行排序也很容易(您不需要考虑具有相同适应度的元素的排序,因为在数组或列表中具有相同适应度的元素没有问题)。
问题内容: 我想用自定义排序顺序在Java中创建一个。字符串排序的键需要根据第二个字符进行排序。这些值也是字符串。 样本图: 问题答案: 您可以像这样使用自定义比较器: 样品: 请注意,这只是假设字符在索引1处有一个字符。 另外,您也可以使用以下比较: 通常,此减法“技巧”是无效的,但在这里可以正常使用,因为减法2 不会溢出。 不过,上面的and 解决方案更具可读性。
我使用的是PriorityQueue和我自己的比较器,但最终结果并不总是好的。我应该按平均成绩、姓名、身份证进行排序。最后,它应该返回队列中剩余的名称。其余的名字都很好,但顺序不同。输入(名称、平均等级、识别号): 预期产出: 我的结果: 你能帮我找出问题所在吗?提前谢谢你!
在我的PriorityQueue中,我有两种类型的客户,即VIP和常规客户。我想先为贵宾服务,再为常客服务。 如果CustomerID<100,则视为VIP。 如果客户是VIP,他会排在队列中VIP部分的最后 更新:我不想排序任何其他列除了VIP。我不想添加“日期”,因为它感觉像是一个黑客,而不是理解Java是如何工作的。
我想按字母顺序对字段名列表进行排序,但是我需要在比较器的doCompare方法中包含一个条件,以便如果字段名是“pk”,则始终将其排序到列表的顶部。我所拥有的内容如下,但我不确定我是否采取了正确的方法,特别是reurn值为-1000。对此的任何建议都将不胜感激。
我创建了一个自定义比较器,可以按降序对获胜数进行排序,但我不确定它是如何工作的,有人能解释一下这是如何按降序排序的吗?
Java在进行比较时抛出的错误是: 然后比较的方法(比较器 你知道发生了什么事吗?