Comment généraliser une méthode pour trier les entrées de carte en Java?


Dans mon code, j'ai quelques cartes. Ensuite, j'ai une méthode comme celle ci-dessous, qui prend une des cartes, trie les entrées par leur valeur et renvoie une liste de la partie supérieure, avec le montant donné par le paramètre.

Exemple:

Si la carte d'entrée est comme

  • "a" = 5,
  • "b" = 4,
  • "c" = 8,
  • "d" = 0,

Et j'appelle la méthode avec quantity = 2 dans le paramètre, on me donne une liste des 2 cartes les plus élevées entrées, triées de manière décroissante

  • "c" = 8,
  • "a" = 5.

En ce moment, j'ai une telle méthode pour chacune des cartes et elles ne diffèrent que par:

  • les déclarations <Type1, Type2> dans toute la méthode, et
  • le (distances.entrySet()); population de la tous les liste.

Puis-je généraliser cela d'une manière ou d'une autre pour n'avoir qu'une seule méthode similaire, pouvant recevoir l'un des types?

private static Map<String, Double>      distances = new TreeMap<>();
private static Map<String, Integer>     titles    = new TreeMap<>();
private static Map<Integer, Integer>    hours     = new TreeMap<>();
private static Map<Date, Integer>       days      = new TreeMap<>();

public static List<Entry<String, Double>> getTopDistances(int quantity) {
    List<Map.Entry<String, Double>> all       = new ArrayList<>(distances.entrySet());
    List<Map.Entry<String, Double>> requested = new ArrayList<>();

    Collections.sort(all, new Comparator<Map.Entry<String, Double>>() {
        @Override
        public int compare(Entry<String, Double> e1, Entry<String, Double> e2) {
            return (e2.getValue().compareTo(e1.getValue()));
        }

    });

    int i = 0;
    while (all.iterator().hasNext() && ++i <= quantity) {
        requested.add(all.get(i - 1));
    }

    return requested;
}

Je peux sûrement continuer avec toutes les méthodes séparées, mais Je sens une meilleure façon de le faire. J'ai recherché génériques, caractères génériques, collections et interfaces , ce qui, je pense, est la voie à suivre, mais j'ai encore besoin d'une poussée.

Author: David Hudec, 2017-03-25

2 answers

Avec Java Streams, une seule ligne peut produire ce que vous voulez de la carte à la liste finale. Ci-dessous, je l'empaquette dans une méthode privée qui est un peu plus soignée mais vous pouvez l'intégrer si vous le souhaitez.

Puisque toutes vos valeurs sont Comparable:

private <K, V extends Comparable<V>> List<Map.Entry<K,V>> getTop(Map<K,V> map, int quantity) {
    return map.entrySet().stream()
           .sorted((a,b) -> b.getValue().compareTo(a.getValue()))
           .limit(quantity)
           .collect(Collectors.toList());
} 

Si le type de valeur n'était pas comparable, vous devrez alors passer le comparateur en tant que paramètre supplémentaire:

private <K, V> List<Map.Entry<K,V>> getTop(Map<K,V> map, Comparator<V> cmp, int quantity) {
    return map.entrySet().stream()
           .sorted((a,b) -> cmp.compare(b,a))
           .limit(quantity)
           .collect(Collectors.toList());
} 
 2
Author: Valentin Ruano, 2017-03-25 14:32:12

Vous ne pouvez pas créer de comparateur qui comparera deux comparables avec des types différents, vous devez donc le faire comme ceci:

private static Map<String, Double> distances = new TreeMap<>();
private static Map<String, Integer>     titles    = new TreeMap<>();
private static Map<Integer, Integer>    hours     = new TreeMap<>();
private static Map<Date, Integer>       days      = new TreeMap<>();

public static List<Map.Entry<String, Double>> getTopDistances(int quantity) {
    List<Map.Entry<String, Double>> all       = new ArrayList<>(distances.entrySet());
    List<Map.Entry<String, Double>> requested = new ArrayList<>();

    all.sort(naturalOrder());

    int i = 0;
    while (all.iterator().hasNext() && ++i <= quantity) {
        requested.add(all.get(i - 1));
    }

    return requested;
}

public static <T extends Comparable<? super T>> Comparator<Map.Entry<?,T> naturalOrder() {
    return (e1, e2) -> e2.getValue().compareTo(e2.getValue());
}
 1
Author: carbolymer, 2017-03-25 14:20:59