如何推广一种方法来对Java中的Map Entries进行排序?

时间:2017-03-25 13:47:58

标签: java generics methods collections treemap

在我的代码中,我有一些地图。然后我有一个类似下面的方法,它采用其中一个映射,按条件对值进行排序,并返回顶部列表,并带有参数给定的数量。

示例:

如果输入地图是

  • "" = 5,
  • " B" = 4,
  • " C" = 8,
  • " d" = 0,

我在参数中用 quantity = 2 调用方法,我给出了2个最高映射条目的列表,逐渐排序

  • " C" = 8,
  • "" = 5。

现在,我为每张地图都有一个这样的方法,它们只有不同之处:

  • 整个方法的<Type1, Type2>声明和
  • 所有列表的(distances.entrySet());人口。

我能否以某种方式推广这个方法,只能使用一种相似的方法,能够接收任何类型的东西吗?

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

我可以肯定继续分离所有方法,但我感觉更好的方法。已经研究过泛型,通配符,集合和接口,我认为这是可行的方法,但我仍然需要推动。

2 个答案:

答案 0 :(得分:2)

使用Java Streams,一行可以将您想要的内容从地图生成到最终列表。贝娄我把它打包成一个私密的方法,它更整洁,但如果你愿意,你可以内联它。

由于您的所有值均为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());
} 

如果值类型不具有可比性,则需要将比较器作为附加参数传递:

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());
} 

答案 1 :(得分:1)

你不能创建比较器来比较两个不同类型的可比对象,所以你必须这样做:

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());
}