Java ImmutableSortedMap-映射中的重复键

Java ImmutableSortedMap-映射中的重复键,java,sorting,guava,comparator,Java,Sorting,Guava,Comparator,我有一个ImmutableSortedMap,它保存以下数据结构中的数据 <String, Pair<Long, Double>> 但是,它会找到两个相同的双精度,并引发以下异常:线程“main”java.lang.IllegalArgumentException中的异常:映射中的重复键 我不明白我做错了什么 编辑:我尝试添加复合方法和按字符串排序(至少) .component(新比较器(){ @凌驾 公共整数比较(字符串o1、字符串o2){ 返回o1。与(o2)相比;

我有一个ImmutableSortedMap,它保存以下数据结构中的数据

<String, Pair<Long, Double>>
但是,它会找到两个相同的
双精度
,并引发以下异常:
线程“main”java.lang.IllegalArgumentException中的异常:映射中的重复键

我不明白我做错了什么

编辑:我尝试添加
复合
方法和按字符串排序(至少)

.component(新比较器(){
@凌驾
公共整数比较(字符串o1、字符串o2){
返回o1。与(o2)相比;
}
});
这使得代码不会抛出任何异常,但是,结果映射中没有任何顺序

编辑2:在这一点上,任何类似于上面描述的

Map<String, Pair<Long, Double>> 
Map
行。不一定需要是ImmutableSortedMap

编辑:用于实际的正确解决方案()。继续阅读此答案以修复错误的方法;)


这是一种记录在案的行为:

抛出:

NullPointerException
-如果映射中的任何键或值为null
IllegalArgumentException
-如果根据比较器,任意两个键相等

你得到的结果是,根据比较器,值相等,所以问题就在那里。-正如Louis提到的(他来自Guava团队),使用
函数.forMap
是很棘手的

在您的情况下,在第一次排序中添加
.nullsLast()
,并在
.component(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)}
}
这是另一种番石榴的好东西,你可以在这里使用。

编辑:实际正确的解决方案()。继续阅读此答案以修复错误的方法;)


这是一种记录在案的行为:

抛出:

NullPointerException
-如果映射中的任何键或值为null
IllegalArgumentException
-如果根据比较器,任意两个键相等

你得到的结果是,根据比较器,值相等,所以问题就在那里。-正如Louis提到的(他来自Guava团队),使用
函数.forMap
是很棘手的

在您的情况下,在第一次排序中添加
.nullsLast()
,并在
.component(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)}
}

是另一种可以在这里使用的来自番石榴的好东西。

ImmutableSortedMap
不是正确的API
ImmutableSortedMap
应该按键排序,这显然不是您要做的

更有意义的是写作

new ImmutableMap.Builder<String, Pair<Long, Double>>()
   .orderEntriesByValue(comparing(Pair::getSecond).thenComparing(Pair::getFirst))
   .putAll(map)
   .build();
newImmutableMap.Builder()
.orderEntriesByValue(比较(Pair::getSecond)。然后比较(Pair::getFirst))
.putAll(地图)
.build();
但是,如果不能使用Java8,则必须显式地编写比较器

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();
  }
}
新比较器(){
@覆盖公共整数比较(对a、对b){
返回ComparisonChain.start()
.compare(a.getSecond(),b.getSecond())
.比较(a.getFirst(),b.getFirst())
.result();
}
}

ImmutableSortedMap
不是适用于此的正确API
ImmutableSortedMap
应该按键排序,这显然不是您要做的

更有意义的是写作

new ImmutableMap.Builder<String, Pair<Long, Double>>()
   .orderEntriesByValue(comparing(Pair::getSecond).thenComparing(Pair::getFirst))
   .putAll(map)
   .build();
newImmutableMap.Builder()
.orderEntriesByValue(比较(Pair::getSecond)。然后比较(Pair::getFirst))
.putAll(地图)
.build();
但是,如果不能使用Java8,则必须显式地编写比较器

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();
  }
}
新比较器(){
@覆盖公共整数比较(对a、对b){
返回ComparisonChain.start()
.compare(a.getSecond(),b.getSecond())
.比较(a.getFirst(),b.getFirst())
.result();
}
}

订购仍然混乱。。。在双精度、长型或StringI编辑的答案和添加的输入映射中,绝对没有排序,包含
{a=(1,1.0),b=(2,1.0),c=(1,2.0),d=(2,2.0)}
并且输出看起来很好:
{d=(2,2.0),b=(2,1.0),c=(1,2.0),a=(1,1.0)
。你能发布你输入的样本数据吗?你期望的输出是什么?它是有效的,我在别的地方出错了。谢谢@xaerxess生成的映射仍将抛出
get(keyNotInMap)
。在这里使用
ImmutableSortedMap
并不是一个好主意。@LouisWasserman是的,
.nullsLast()
丢失了。如前所述,这是一个棘手的问题-添加到您的简单答案的参考。排序仍然混乱。。。在双精度、长型或StringI编辑的答案和添加的输入映射中,绝对没有排序,包含
{a=(1,1.0),b=(2,1.0),c=(1,2.0),d=(2,2.0)}
并且输出看起来很好:
{d=(2,2.0),b=(2,1.0),c=(1,2.0),a=(1,1.0)
。你能发布你输入的样本数据吗?你期望的输出是什么?它是有效的,我在别的地方出错了。谢谢@xaerxess生成的映射仍将抛出
get(keyNotInMap)
。在这里使用
ImmutableSortedMap
并不是一个好主意。@LouisWasserman是的,
.nullsLast()
丢失了。如前所述,这是一个棘手的问题-添加了对您更简单答案的引用。关于
ImmutableMap.Builder#orderEntriesByValue
-非常简洁(从19.0开始就没有看到过这一点,这是
)!OP希望对这两个对值进行排序,并且似乎在Java上对
ImmutableMap.Builder#orderEntriesByValue
进行排序-这很整洁(从19.0开始就没有看到过,这是
)!OP希望对这两个对值进行排序,而且似乎在Java上
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();
  }
}