【问题标题】:Finding the max of a list of arrays using custom comparator使用自定义比较器查找数组列表的最大值
【发布时间】:2019-09-01 08:12:00
【问题描述】:

我有一个如下所示的早餐课程:

class Breakfast {

     String[] fruits;
     ...

     // Getter and Setter here
     ...
}

fruits 字段始终是一个大小为 2 的数组,包含以下三个可能值之一:{"apple", "pear"}, {"apple", "grape"}, {"pear", "grape"}

我为这三个值设计了一个自定义顺序,如下所示:

    String[] orderOne = {"apple", "pear"};
    String[] orderTwo = {"apple", "grape"};
    String[] orderThree = {"pear", "grape"};

并且我编写了自己的自定义比较器:

    List<String[]> breakfastOrder = Arrays.asList(orderOne, orderTwo, orderThree);

    Comparator<Breakfast> orderComparator = Comparator.comparing(b -> breakfastOrder.indexOf(new String[] {breakfast.getFruits()[0], breakfast.getFruits()[1]});

在处理早餐对象列表时,我希望找到“最大”水果组合。

换句话说,如果找到 {"pear", "grape"},则 {"pear", "grape"} 将是“Max”。如果没有找到 {"pear", "grape"},但找到了 {"apple", "grape"},则 {"apple", "grape"} 将是最大值。

当我有早餐对象列表时,如何找到“最大值”?流有一个 max 函数,我可以将它与我的自定义比较器一起使用吗?

我在想这样的事情:

List<Breakfast> bList = //initialize the list

String[] max = bList.stream.max(orderComparator).get().getFruits();

如果 Java 11 中的任何部分发生了变化,请告诉我。另外,如果我的代码有任何问题或者我的逻辑/实现是否有缺陷,请告诉我。

【问题讨论】:

  • @AndyTurner 虽然不是按字母顺序排列
  • 我投票结束这个问题,因为它属于codereview.stackexchange.com
  • 数组没有基于内容的equals 方法,因此breakfastOrder.indexOf(new String[] { … }) 将始终为-1,因为无法在列表中找到新创建的数组。即使您删除了那个过时的复制操作广告使用breakfastOrder.indexOf(breakfast.getFruits()),它也只有在数组是相同的对象实例时才有效。

标签: java java-8 java-stream comparator


【解决方案1】:

如果您可以将equals/hashCode 覆盖为Breakfast,则在此处简化(不要这样写等于):

    @Override
    public int hashCode() {
        return Arrays.hashCode(fruits);
    }

    @Override
    public boolean equals(Object other) {
        Breakfast b = (Breakfast) other;
        return Arrays.equals(b.getFruits(), getFruits());
    }

您可以创建一个Map 并保留索引(如果您愿意,可以将其视为比较器的强度):

 Map<Breakfast, Integer> MAP = ImmutableMap.of(
        new Breakfast(new String[]{"pear", "grape"}), 1,
        new Breakfast(new String[]{"apple", "grape"}), 2,
        new Breakfast(new String[]{"apple", "pear"}), 3);

并通过以下方式对它们进行排序:

Breakfast max = Collections.max(
        yourListOfGrapes,
        Comparator.comparingInt(b -> Optional.ofNullable(MAP.get(b)).orElse(0))
                  .reversed());

【讨论】:

  • MAP.getOrDefault(b, 0)...
【解决方案2】:

因为您是手动定义货币对的顺序/优先级。您可以通过在 String 数组中添加 order# 使其具有 3 个元素大小来简化您的工作。 现在您可以对数组的第三个成员进行排序/最大值/最小值。

String[] orderOne = { "apple", "pear", "1" };
    String[] orderTwo = { "apple", "grape", "2" };
    String[] orderThree = { "pear", "grape", "3" };

    List<String[]> bList = Arrays.asList(orderOne, orderTwo, orderThree);
    String[] max = bList.stream().max((a, b) -> a[2].compareTo(b[2])).get();
    System.out.println(Arrays.toString(max));

【讨论】:

    猜你喜欢
    • 2011-08-02
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    相关资源
    最近更新 更多