简体   繁体   English

如何在Java中对多图进行排序?

[英]How to sort a multimap in Java?

So I am trying to sort a multimap in Java, here's what the maps looks like: 所以我试图用Java对多图进行排序,这是图的样子:

Map<Integer, Pair<Double, Color>> inputMap;
Map<Integer, Pair<Double, Color>> outputMap;

and here is my Pair class: 这是我的配对课程:

class Pair<Double, Color> {
  public final Double x;
  public final Color y;
  public Pair(Double x, Color y) {
    this.x = x;
    this.y = y;
  }
}

I am trying to sort it by the first item of Pair. 我正在尝试按配对的第一项进行排序。 I tried to use something like this: 我试图使用这样的东西:

outputMap = new TreeMap<>(inputMap);

but that doesn't exactly work how I thought it would... It doesn't seem to sort it at all. 但这并不完全符合我的预期……似乎根本无法对其进行排序。

How would I sort the map by Pair.X? 如何按Pair.X对地图排序?

All SortedMap implementations (including TreeMap ) sort by the key not by value . 所有SortedMap实现(包括TreeMap )均key而不是按value排序。

https://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html https://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html

A Map that further provides a total ordering on its keys. 进一步提供其键的总体排序的Map。

Sorting the Map internally by value also would be bad for the performance which is optimised for access through the key . 在内部按valueMap排序也不利于针对通过key访问进行优化的性能。


A Map only ever associates one value to each key. Map只会将一个值与每个键相关联。

This becomes especially clear when you look at the documentation of put 当您查看put的文档时,这一点尤其明显

Associates the specified value with the specified key in this map (optional operation). 将指定值与该映射中的指定键关联(可选操作)。 If the map previously contained a mapping for the key, the old value is replaced by the specified value. 如果该映射先前包含该键的映射,则旧值将替换为指定值。

So what you defined with Map<Integer, Pair<Double, Color>> is not even a MultiMap . 因此,您使用Map<Integer, Pair<Double, Color>>定义的甚至不是MultiMap Which explains why it does not behave how you expect it to. 这就解释了为什么它不符合您的预期。


What you are looking for is a SortedSetMultimap 您正在寻找的是SortedSetMultimap

A SetMultimap whose set of values for a given key are kept sorted; 一个SetMultimap,其给定键的值集保持排序; that is, they comprise a SortedSet. 也就是说,它们包含一个SortedSet。

With

//Class renamed to reflect what it actually is, to avoid conflicts with other Pairs. Also you don't need generics then, which you did not use any way.
class ColorPair implements Comparable {
  public final Double x;
  public final Color y;
  public ColorPair (Double x, Color y) {
    this.x = x;
    this.y = y;
  }

  //compares only the first component of the Pair
  public int compareTo(ColorPair  other){
    return Double.compare(x, other.x)
  }

}

Then you can create the SortedSetMultimap with 然后您可以使用以下命令创建SortedSetMultimap

TreeMultimap<Integer, ColorPair> sortedSetMap = new TreeMultimap<>() `

and fill it with the ColorPair s 并用ColorPair填充它

You can't sort by map values - by keys only. 您不能按地图值排序-仅按键排序。

If you need both - HashMap for O(1) access to objects and sorted traversal - create a sorted list and keep same objects there. 如果同时需要两者-用于对象的O(1)的HashMap访问对象和排序遍历-创建一个排序列表并将相同的对象保留在那里。

List<Pair<Double, Object>>outputList = inputMap.values().stream().sorted((o1, o2) -> 0 /*IMPLEMENT_COMPARATOR_HERE*/).collect(Collectors.toList());

If the map is mutable - it would be better to create a class that will contain both - map and list - and provide methods like "add" "get" and "remove". 如果地图是可变的-最好创建一个同时包含地图和列表的类,并提供“添加”,“获取”和“删除”之类的方法。 Direct access to those structures should be avoided. 应避免直接访问这些结构。

Don't forget to synchronize operations on both data structures to make your code thread safe. 不要忘记同步两个数据结构上的操作,以确保您的代码线程安全。

Highlight 突出

You can sort the map using: 您可以使用以下方法对地图进行排序:

Map<Integer, Pair<Double, Color>> sortedMap = map.entrySet().stream()
        .sorted(Comparator.comparingDouble(e -> e.getValue().x))
        .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (p1, p2) -> p1,
                LinkedHashMap::new));

Full code 完整代码

public static void main(String[] args) {
    new MyClass().test();
}

public void test() {
    Map<Integer, Pair<Double, Color>> map = Map.of(
            1, new Pair<>(1.0, Color.BLACK),
            2, new Pair<>(3.0, Color.RED),
            3, new Pair<>(2.0, Color.BLUE));

    Map<Integer, Pair<Double, Color>> sortedMap = map.entrySet().stream()
            .sorted(Comparator.comparingDouble(e -> e.getValue().x))
            .collect(Collectors.toMap(
                    Map.Entry::getKey,
                    Map.Entry::getValue,
                    (p1, p2) -> p1,
                    LinkedHashMap::new));

    System.out.println(sortedMap);
}

class Pair<Double, Color> {
    public final Double x;
    public final Color y;

    public Pair(Double x, Color y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Pair<?, ?> pair = (Pair<?, ?>) o;
        return Objects.equals(x, pair.x) &&
                Objects.equals(y, pair.y);
    }

    @Override
    public int hashCode() {

        return Objects.hash(x, y);
    }

    @Override
    public String toString() {
        return "Pair{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}

Output 产量

{1=Pair{x=1.0, y=java.awt.Color[r=0,g=0,b=0]}, 3=Pair{x=2.0, y=java.awt.Color[r=0,g=0,b=255]}, 2=Pair{x=3.0, y=java.awt.Color[r=255,g=0,b=0]}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM