可按值顺序迭代的映射

2022-09-03 05:23:16

我需要一个可以按其值的递减顺序迭代的 Map。是否有任何标准库(如Apache Commons或Guava)提供这种地图?


答案 1

我会用番石榴这样做,如下所示:

Ordering<Map.Entry<Key, Value>> entryOrdering = Ordering.from(valueComparator)
  .onResultOf(new Function<Entry<Key, Value>, Value>() {
    public Value apply(Entry<Key, Value> entry) {
      return entry.getValue();
    }
  }).reverse();
// Desired entries in desired order.  Put them in an ImmutableMap in this order.
ImmutableMap.Builder<Key, Value> builder = ImmutableMap.builder();
for (Entry<Key, Value> entry : 
    entryOrdering.sortedCopy(map.entrySet())) {
  builder.put(entry.getKey(), entry.getValue());
}
return builder.build();
// ImmutableMap iterates over the entries in the desired order

答案 2

使用番石榴,有比@LoisWasserman的肛门更干净的方式 - 使用Ordering与Functions.forMap相结合:

Ordering.natural().reverse().nullsLast().onResultOf(Functions.forMap(map, null))

或者如果值不是 :Comparable

Ordering.fromComparator(yourComparator).reverse().nullsLast().onResultOf(Functions.forMap(map, null))

示例(使用第一个选项 - 自然排序):

final Map<String, String> map = ImmutableMap.of(
    "key 1", "value 1",
    "key 2", "value 2",
    "key 3", "another value",
    "key 4", "zero value");

final Ordering<String> naturalReverseValueOrdering =
    Ordering.natural().reverse().nullsLast().onResultOf(Functions.forMap(map, null));

System.out.println(ImmutableSortedMap.copyOf(map, naturalReverseValueOrdering));

输出:

{key 4=zero value, key 2=value 2, key 1=value 1, key 3=another value}

(我在这里使用ImmutableSortedMap,但如果需要可变性,也可以使用TreeMap

编辑

如果存在相同的值(如果存在两个返回 0 的值,则更确切地说),ImmutableSortedMap 将引发异常。排序不得返回,因此,如果两个值相等(键不应相等),则应使用 Ordering.compound 将 map 按值先排序,然后按键排序:Comparator.compare(String v1, String v2)

final Map<String, String> map = ImmutableMap.of(
    "key 1", "value 1",
    "key 2", "value 2",
    "key 3", "zero value",
    "key 4", "zero value");

final Ordering<String> reverseValuesAndNaturalKeysOrdering =
    Ordering.natural().reverse().nullsLast().onResultOf(Functions.forMap(map, null)) // natural for values
        .compound(Ordering.natural()); // secondary - natural ordering of keys

System.out.println(ImmutableSortedMap.copyOf(map, reverseValuesAndNaturalKeysOrdering));

指纹:

{key 3=zero value, key 4=zero value, key 2=value 2, key 1=value 1}