1
votes

Comment trier une multimap en Java?

Donc j'essaye de trier une multi-carte en Java, voici à quoi ressemblent les cartes:

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

et voici ma classe Pair:

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


3 commentaires

Toutes les implémentations de SortedMap sont triées par clé pas par valeur . Voulez-vous trier par la clé Integer et le Double de la paire ou juste le double?


Le tri implique l'ordre. Lorsque vous voulez être en mesure de trier ces objets paires, vous devez définir (d'abord conceptuellement, puis dans le code) ce qui fait paire1


Ce n'est pas une multi-carte.


3 Réponses :


1
votes

Vous ne pouvez pas trier par valeurs de carte - par clés uniquement.

Si vous avez besoin des deux - HashMap pour O (1) accès aux objets et parcours trié - créez une liste triée et y gardez les mêmes objets.

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

Si la carte est mutable - il serait préférable de créer une classe qui contiendra à la fois - map et list - et fournir des méthodes telles que "add" "get" et " supprimer". L'accès direct à ces structures doit être évité.

N'oubliez pas de synchroniser les opérations sur les deux structures de données pour sécuriser votre thread de code.


0 commentaires

3
votes

Tous les SortedMap les implémentations (y compris TreeMap ) trient par la clé et non par value. final

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

Une carte qui fournit en outre un ordre total sur ses clés.

Le tri de la Carte en interne par valeur serait également mauvais pour les performances qui sont optimisées pour l'accès via la touche .


Un Map n'associe jamais qu'une seule valeur à chaque clé.

Cela devient particulièrement clair lorsque vous consultez la documentation de put

Associe la valeur spécifiée à la clé spécifiée dans cette carte (opération facultative). Si la carte contenait auparavant un mappage pour la clé, l'ancienne valeur est remplacée par la valeur spécifiée.

Donc, ce que vous avez défini avec Map > n'est même pas un MultiMap . Ce qui explique pourquoi il ne se comporte pas comme vous l'attendez.


Ce que vous recherchez est un SortedSetMultimap

Un SetMultimap dont l'ensemble de valeurs pour une clé donnée est conservé trié; autrement dit, ils comprennent un SortedSet.

Avec

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

Ensuite, vous pouvez créer le SortedSetMultimap avec

//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)
  }

}

et le remplir avec le ColorPairs


0 commentaires

0
votes

Vous pouvez trier la carte en utilisant:

{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]}}

Code complet

XXX

Sortie

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 +
                '}';
    }
}


0 commentaires