ImmutableSortedMap - 映射中的重复键
ImmutableSortedMap - Duplicate keys in mappings
我有一个 ImmutableSortedMap 将数据保存在以下数据结构中。
<String, Pair<Long, Double>>
我的目标是从最大的 Double
开始按降序对这张地图进行排序,如果两个 Doubles
相同,则按 Long
对其进行排序。如果 Double
和 Long
相同,则按 String
排序
我目前的比较器只处理第一种情况,看起来像这样。
private ImmutableSortedMap<String, Pair<Long, Double>> sortInDescendingSizeOrder(final Map<String, Pair<Long, Double>> statsByType) {
Ordering<String> ordering = Ordering
.from(new Comparator<Pair<Long, Double>>() {
@Override
public int compare(Pair<Long, Double> o, Pair<Long, Double> o2) {
return o.getRight().equals(o2.getRight()) ? o.getLeft().compareTo(o2.getLeft()) : o.getRight().compareTo(o2.getRight());
}
})
.reverse()
.onResultOf(Functions.forMap(statsByType, null));
return ImmutableSortedMap.copyOf(statsByType, ordering);
}
但是,它发现两个相同的 Doubles
并抛出以下异常:Exception in thread "main" java.lang.IllegalArgumentException: Duplicate keys in mappings
我不明白我做错了什么...
编辑:我尝试添加 compound
方法并按字符串排序(至少)。
.compound(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
这使得代码不会抛出任何异常,但是,结果映射中没有任何顺序。
编辑 2:此时,任何类似于上述
的排序
Map<String, Pair<Long, Double>>
会的。不一定需要是 ImmutableSortedMap
编辑: for actual proper solution (ImmutableMap.Builder#orderEntriesByValue(Comparator)
)。继续阅读此答案以修复不正确的方法 ;)
这是 ImmutableSortedMap#copyOf(Map, Comparator)
的记录行为:
Throws:
NullPointerException
- if any key or value in map is null
IllegalArgumentException
- if any two keys are equal according to the comparator
你得到的是根据比较器值相等的结果,所以问题就在那里。 See this answer for comparing map by value - 正如 Louis 提到的(他来自 Guava 团队),使用 Functions.forMap
很棘手。
在您的情况下,将 .nullsLast()
添加到第一个排序并附加 .compound(Ordering.natural())
应该可行。例如:
Map<String, Pair<Long, Double>> map = ImmutableMap.of(
"a", Pair.of(1L, 1.0d),
"b", Pair.of(1L, 1.0d),
"c", Pair.of(1L, 1.0d),
"d", Pair.of(1L, 1.0d)
);
@Test
public void should2()
{
final ImmutableSortedMap<String, Pair<Long, Double>> sortedMap = sortInDescendingSizeOrder(map);
assertThat(sortedMap).hasSize(4);
System.out.println(sortedMap); // {a=(1,1.0), b=(1,1.0), c=(1,1.0), d=(1,1.0)}
}
和
Map<String, Pair<Long, Double>> map = ImmutableMap.of(
"a", Pair.of(1L, 1.0d),
"b", Pair.of(2L, 1.0d),
"c", Pair.of(1L, 2.0d),
"d", Pair.of(2L, 2.0d)
);
输出{d=(2,2.0), b=(2,1.0), c=(1,2.0), a=(1,1.0)}
.
(sortInDescendingSizeOrder
供参考)
private ImmutableSortedMap<String, Pair<Long, Double>> sortInDescendingSizeOrder(
final Map<String, Pair<Long, Double>> statsByType) {
Ordering<String> ordering = Ordering.from(new Comparator<Pair<Long, Double>>() {
@Override
public int compare(Pair<Long, Double> o, Pair<Long, Double> o2) {
return ComparisonChain.start()
.compare(o.getRight(), o2.getRight())
.compare(o.getLeft(), o2.getLeft())
.result();
}
})
.reverse()
.nullsLast()
.onResultOf(Functions.forMap(statsByType, null))
.compound(Ordering.natural());
return ImmutableSortedMap.copyOf(statsByType, ordering);
}
ComparisonChain
是 Guava 的另一个好东西,你可以在这里使用。
ImmutableSortedMap
是 而不是 正确的 API。 ImmutableSortedMap
应该按 键 排序,而这显然不是您正在做的。
更有意义的是写作
new ImmutableMap.Builder<String, Pair<Long, Double>>()
.orderEntriesByValue(comparing(Pair::getSecond).thenComparing(Pair::getFirst))
.putAll(map)
.build();
不过,如果您不能使用 Java 8,则必须显式编写比较器
new Comparator<Pair<Long, Double>>() {
@Override public int compare(Pair<Long, Double> a, Pair<Long, Double> b) {
return ComparisonChain.start()
.compare(a.getSecond(), b.getSecond())
.compare(a.getFirst(), b.getFirst())
.result();
}
}
我有一个 ImmutableSortedMap 将数据保存在以下数据结构中。
<String, Pair<Long, Double>>
我的目标是从最大的 Double
开始按降序对这张地图进行排序,如果两个 Doubles
相同,则按 Long
对其进行排序。如果 Double
和 Long
相同,则按 String
我目前的比较器只处理第一种情况,看起来像这样。
private ImmutableSortedMap<String, Pair<Long, Double>> sortInDescendingSizeOrder(final Map<String, Pair<Long, Double>> statsByType) {
Ordering<String> ordering = Ordering
.from(new Comparator<Pair<Long, Double>>() {
@Override
public int compare(Pair<Long, Double> o, Pair<Long, Double> o2) {
return o.getRight().equals(o2.getRight()) ? o.getLeft().compareTo(o2.getLeft()) : o.getRight().compareTo(o2.getRight());
}
})
.reverse()
.onResultOf(Functions.forMap(statsByType, null));
return ImmutableSortedMap.copyOf(statsByType, ordering);
}
但是,它发现两个相同的 Doubles
并抛出以下异常:Exception in thread "main" java.lang.IllegalArgumentException: Duplicate keys in mappings
我不明白我做错了什么...
编辑:我尝试添加 compound
方法并按字符串排序(至少)。
.compound(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
这使得代码不会抛出任何异常,但是,结果映射中没有任何顺序。
编辑 2:此时,任何类似于上述
的排序Map<String, Pair<Long, Double>>
会的。不一定需要是 ImmutableSortedMap
编辑:ImmutableMap.Builder#orderEntriesByValue(Comparator)
)。继续阅读此答案以修复不正确的方法 ;)
这是 ImmutableSortedMap#copyOf(Map, Comparator)
的记录行为:
Throws:
NullPointerException
- if any key or value in map is null
IllegalArgumentException
- if any two keys are equal according to the comparator
你得到的是根据比较器值相等的结果,所以问题就在那里。 See this answer for comparing map by value - 正如 Louis 提到的(他来自 Guava 团队),使用 Functions.forMap
很棘手。
在您的情况下,将 .nullsLast()
添加到第一个排序并附加 .compound(Ordering.natural())
应该可行。例如:
Map<String, Pair<Long, Double>> map = ImmutableMap.of(
"a", Pair.of(1L, 1.0d),
"b", Pair.of(1L, 1.0d),
"c", Pair.of(1L, 1.0d),
"d", Pair.of(1L, 1.0d)
);
@Test
public void should2()
{
final ImmutableSortedMap<String, Pair<Long, Double>> sortedMap = sortInDescendingSizeOrder(map);
assertThat(sortedMap).hasSize(4);
System.out.println(sortedMap); // {a=(1,1.0), b=(1,1.0), c=(1,1.0), d=(1,1.0)}
}
和
Map<String, Pair<Long, Double>> map = ImmutableMap.of(
"a", Pair.of(1L, 1.0d),
"b", Pair.of(2L, 1.0d),
"c", Pair.of(1L, 2.0d),
"d", Pair.of(2L, 2.0d)
);
输出{d=(2,2.0), b=(2,1.0), c=(1,2.0), a=(1,1.0)}
.
(sortInDescendingSizeOrder
供参考)
private ImmutableSortedMap<String, Pair<Long, Double>> sortInDescendingSizeOrder(
final Map<String, Pair<Long, Double>> statsByType) {
Ordering<String> ordering = Ordering.from(new Comparator<Pair<Long, Double>>() {
@Override
public int compare(Pair<Long, Double> o, Pair<Long, Double> o2) {
return ComparisonChain.start()
.compare(o.getRight(), o2.getRight())
.compare(o.getLeft(), o2.getLeft())
.result();
}
})
.reverse()
.nullsLast()
.onResultOf(Functions.forMap(statsByType, null))
.compound(Ordering.natural());
return ImmutableSortedMap.copyOf(statsByType, ordering);
}
ComparisonChain
是 Guava 的另一个好东西,你可以在这里使用。
ImmutableSortedMap
是 而不是 正确的 API。 ImmutableSortedMap
应该按 键 排序,而这显然不是您正在做的。
更有意义的是写作
new ImmutableMap.Builder<String, Pair<Long, Double>>()
.orderEntriesByValue(comparing(Pair::getSecond).thenComparing(Pair::getFirst))
.putAll(map)
.build();
不过,如果您不能使用 Java 8,则必须显式编写比较器
new Comparator<Pair<Long, Double>>() {
@Override public int compare(Pair<Long, Double> a, Pair<Long, Double> b) {
return ComparisonChain.start()
.compare(a.getSecond(), b.getSecond())
.compare(a.getFirst(), b.getFirst())
.result();
}
}