当前位置: 首页 > 知识库问答 >
问题:

Java8流:检查我的对象实例的两个字段的列表顺序是否正确

欧阳鸿哲
2023-03-14

标题可能有点模糊,但以下是我的(私有化代码):

包含一些字段的类,包括BigDecimal和Date:

class MyObj{
  private java.math.BigDecimal percentage;
  private java.util.Date date;
  // Some more irrelevant fields

  // Getters and Setters
}

在另一个类中,我有这些对象的列表(即java.util.List

例如,下面的列表是真实的:

[ MyObj { percentage = 25, date = 01-01-2018 },
  MyObj { percentage = 50, date = 01-02-2018 },
  MyObj { percentage = 100, date = 15-04-2019 } ]

但是这个列表是错误的,因为百分比的顺序不正确:

[ MyObj { percentage = 25, date = 01-01-2018 },
  MyObj { percentage = 20, date = 01-02-2018 },
  MyObj { percentage = 100, date = 15-04-2019 } ]

这个列表也是错误的,因为日期顺序不正确:

[ MyObj { percentage = 25, date = 10-03-2018 },
  MyObj { percentage = 50, date = 01-02-2018 },
  MyObj { percentage = 100, date = 15-04-2019 } ]

一个可能的解决方案可能是像这样创建,然后使用 。anyMatch检查每个

有没有办法使用。减少或使用某种方法在成对的MyObj上循环检查它们?使用Java8流检查我的列表中的MyObj的所有日期和百分比的顺序是否正确,最好的方法是什么?

另一种可能是按日期对列表进行排序,然后检查它们是否都按百分比排序,如果这比同时检查两个字段容易的话。不过,在比较MyObj的百分比时,同样的问题仍然存在。

(注:我将把它用于com.vaadin.server.SerializablePredicate。)


共有3个答案

伍耀
2023-03-14

既然您已经提到,您不想为此创建一个单独的类Pairs,那么您可以使用一个内置类来实现这样的目的:AbstractMap。SimpleEntry

您可以制作一个BiPredicate,检查两种比较条件

BiPredicate<MyObj,MyObj> isIncorrectOrder = (o1,o2) -> {
    boolean wrongOrder = o1.getDate().after(o2.getDate());
    return wrongOrder ? wrongOrder : o1.getPercentage().compareTo(o2.getPercentage()) > 0;
};

boolean isNotSorted =  IntStream.range(1,myObjs.size())
        .anyMatch(i -> isIncorrectOrder.test(myObjs.get(i-1),myObjs.get(i)));

上述带有比较器的解决方案:

Comparator<MyObj> comparator = (o1, o2) -> {
    boolean wrongOrder = o1.getDate().after(o2.getDate());
    return wrongOrder ? 1 : o1.getPercentage().compareTo(o2.getPercentage());
};

Predicate<AbstractMap.SimpleEntry<MyObj,MyObj>> isIncorrectOrder = pair ->  comparator.compare(pair.getKey(),pair.getValue()) > 0;

boolean isNotSorted =  IntStream.range(1,myObjs.size())
         .mapToObj(i -> new AbstractMap.SimpleEntry<>(myObjs.get(i-1),myObjs.get(i)))
         .anyMatch(isIncorrectOrder);
许博达
2023-03-14

我认为你几乎是通过尝试使用Stream.any匹配。你可以这样完成它:

private static boolean isNotOrdered(List<MyObj> myList) {
    return IntStream.range(1, myList.size()).anyMatch(i -> isNotOrdered(myList.get(i - 1), myList.get(i)));

}

private static boolean isNotOrdered(MyObj before, MyObj after) {
    return before.getPercentage().compareTo(after.getPercentage()) > 0 ||
            before.getDate().compareTo(after.getDate()) > 0;
}

我们可以使用IntStream。range使用索引迭代列表中的元素。通过这种方式,我们可以参考列表中的任何元素,例如前一个元素来进行比较。

编辑添加更通用的版本:

private static boolean isNotOrderedAccordingTo(List<MyObj> myList, BiPredicate<MyObj, MyObj> predicate) {
    return IntStream.range(1, myList.size()).anyMatch(i-> predicate.test(myList.get(i - 1), myList.get(i)));
}

使用上述谓词可以如下调用:

isNotOrderedAccordingTo(myList1, (before, after) -> isNotOrdered(before, after));

或者在类ListNotOrder中使用方法引用:

isNotOrderedAccordingTo(myList1, ListNotOrdered::isNotOrdered)
华星剑
2023-03-14

如果你想要一个短路操作,我不认为存在使用流api的简单解决方案。。。我提出了一个更简单的方法,首先定义一个方法,该方法将以一种短路的方式告诉您,根据某些参数,列表是否已排序:

 private static <T, R extends Comparable<? super R>> boolean isSorted(List<T> list, Function<T, R> f) {
    Comparator<T> comp = Comparator.comparing(f);
    for (int i = 0; i < list.size() - 1; ++i) {
        T left = list.get(i);
        T right = list.get(i + 1);
        if (comp.compare(left, right) >= 0) {
            return false;
        }
    }

    return true;
}

并通过以下方式调用:

 System.out.println(
          isSorted(myList, MyObj::getPercentage) && 
          isSorted(myList, MyObj::getDate));
 类似资料:
  • 我有一个Java类,它有20个属性及其相应的getter和setter。还有两个对象列表:和。 使用Java 8: 但是我必须在哪个地方指定属性呢?是否应该重写和方法?

  • 我有两个arraylist。employee类和user类的ArrayList。employee类将name、age、address作为字段。用户类将名称、年龄、地址作为字段。下面是两个列表 要检查用户是否和员工的地址相同。如果用户没有地址,则从员工处复制。

  • 我有一个创建Element类型arraylist的主类: 然后我有一个元素clas: 我想在将一个元素添加到列表(它的id和名称)之前进行检查,以检查列表中已经存在的另一个元素是否已经具有这些精确值(id和名称)。我知道我可以使用toString方法来实现这一点,但我不确定如何在将元素添加到列表之前重写它以传递id和名称。他们是这样做的吗?理想情况下,我只想添加一个元素,如果它还不存在的话。

  • 对于此示例: 如何检查 是否是 Foo 的实例(但不是其 foo 子类的实例)?那是: checkInstance(qux,Foo.class)=true checkInstance(qux,Bar.class)=false 有没有类似于< code>instanceof的语句来进行这种检查?或者我应该使用< code>qux.getClass()。equals(Foo.class)

  • 我有这样的想法: 我怎么能把它写在一个流中呢?收集f.e.

  • 对于这个示例: null 是否有类似这样的语句用于此检查?或者我应该使用