无法理解 Predicate isEqual 方法
Unable to get my head around Predicate isEqual method
在 Java 文档中给出 -
Modifier and Type Method and Description
static <T> Predicate<T> isEqual(Object targetRef)
Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
在https://www.geeksforgeeks.org/java-8-predicate-with-examples/
给出-
isEqual(Object targetRef) : Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
static Predicate isEqual(Object targetRef)
Returns a predicate that tests if two arguments are
equal according to Objects.equals(Object, Object).
T : the type of arguments to the predicate
Parameters:
targetRef : the object reference with which to
compare for equality, which may be null
Returns: a predicate that tests if two arguments
are equal according to Objects.equals(Object, Object)
我无法理解这个 Objects.equals(Object, Object)
可能是什么
我写了下面的代码试试看-
Class 水果 -
Fruits.java
-
public class Fruits {
private String fruit;
public Fruits(String fruit) {
this.fruit = fruit;
}
public String getFruit() {
return fruit;
}
}
到这里,predicate的其他方法好像还挺容易理解的-
Predicate<List<Fruits>> containsApple = list -> {
boolean myReturn = false;
Iterator<Fruits> iterator = list.iterator();
while (iterator.hasNext()) {
Fruits fruits = iterator.next();
String fruit = fruits.getFruit();
if (fruit.equals("Apple")) {
myReturn = true;
break;
}
}
return myReturn;
};
Predicate<List<Fruits>> containsOrange = list -> {
boolean myReturn = false;
Iterator<Fruits> iterator = list.iterator();
while (iterator.hasNext()) {
Fruits fruits = iterator.next();
String fruit = fruits.getFruit();
if (fruit.equals("Orange")) {
myReturn = true;
break;
}
}
return myReturn;
};
Predicate<List<Fruits>> containsAppleAndOrange = list -> {
return containsApple.and(containsOrange).test(list);
};
Predicate<List<Fruits>> containsAppleOrRange = list -> {
return containsApple.or(containsOrange).test(list);
};
Predicate<List<Fruits>> notContainsApple = list -> {
return containsApple.negate().test(list);
};
Predicate<List<Fruits>> notContainsOrange = list -> {
return containsOrange.negate().test(list);
};
Predicate<List<Fruits>> notContainsAppleAndOrange = list -> {
return containsAppleAndOrange.negate().test(list);
};
Predicate<List<Fruits>> notContainsAppleOrOrange = list -> {
return containsAppleOrRange.negate().test(list);
};
这里我用下面的数据进行测试-
List<Fruits> list1 = new ArrayList<>(List.of(
new Fruits("Apple"),
new Fruits("Orange"),
new Fruits("Mango"),
new Fruits("Banana")
));
List<Fruits> list2 = new ArrayList<>(List.of(
new Fruits("Apple"),
new Fruits("Mango"),
new Fruits("Banana"),
new Fruits("Berry")
));
List<Fruits> list3 = new ArrayList<>(List.of(
new Fruits("Orange"),
new Fruits("Mango"),
new Fruits("Banana"),
new Fruits("Berry")
));
结果符合预期。
但是我完全无法理解如何实现 isEqual()
方法 -
要查看两个参数是否相等,我创建了另一个谓词 -
redicate<List<Fruits>> containsApple2 = list -> {
boolean myReturn = false;
Iterator<Fruits> iterator = list.iterator();
while (iterator.hasNext()) {
Fruits fruits = iterator.next();
String fruit = fruits.getFruit();
if (fruit.equals("Apple")) {
myReturn = true;
break;
}
}
return myReturn;
};
我尝试类似(不明白为什么)-
System.out.println(Predicate.isEqual(containsApple).test(list1));
输出 - false
现在这里发生了什么?
System.out.println(Predicate.isEqual(containsApple2).test(containsApple));
输出 - false
现在又发生了什么事?
那么,这个isEqual
方法具体怎么用呢?
Predicate.isEqual
是一个工厂方法,它创建谓词来测试给定的事物是否等于传入的参数。
Predicate.isEqual(containsApple)
创建一个 Predicate<Predicate<List<Fruits>>>
来测试给定的事物是否等于 containsApple
。但是,由于 containsApple
指的是从 lambda 创建的实例,并且对于从 lambda 表达式创建的实例的相等性并没有太多保证(参见 JLS),所以关于结果没有什么可以说的在上面调用 test
。 lambda 实例的 类 可能实现也可能不实现 equals
,并且 containsApple
可能与 containsApple2
是同一实例,也可能不同,具体取决于实现。
而不是比较 lambda 实例,使用 Predicate.isEqual
的典型示例是:
Fruits apple = new Fruits("Apple");
Predicate<Fruits> isApple = Predicate.isEqual(apple);
// rather than this slightly longer version:
// Predicate<Fruits> isApple = x -> Objects.equals(x, apple);
然后你可以将 isApple
传递给其他需要 Predicate
s 的方法,and/or 调用 test
就可以了。 isApple.test(apple)
为真,isApple.test(new Fruits("something else"))
为假。我还建议您在 Fruits
.
中覆盖 equals
和 hashCode
请注意,我们通常使用谓词来测试单个对象,而不是事物列表(集合)。我们会将这些谓词传递给其他方法(例如 Stream.filter
),并让 它们 进行过滤。例如,要过滤列表以获取所有苹果:
List<Fruits> apples = fruitsList.stream()
.filter(Predicate.isEqual(apple)).toList();
这里 class 水果应该用单数。
首先你必须建立水果的平等。如果您希望它存储在 HashMap 或 HashSet 中,hashCode
实现也很重要。
public class Fruit {
private final String fruit; // Or name.
public Fruit(String fruit) {
this.fruit = fruit;
}
public String getFruit() {
return fruit;
}
@Override
public boolean equals(Object other) {
return other instanceOf Fruit && ((Fruit) other).fruit.equals(fruit);
}
@Override
public int hashCode() {
return fruit.hashCode();
}
}
迭代器 class 相当陈旧,它的主要优点是您可以遍历并仍然使用 iterator.remove()
删除元素,这在 - statefull - for ( ConcurrentModificationException).
Predicate<List<Fruit>> containsApple = list -> {
for (Fruit fruit: list) {
if (fruit.getFruit().equals("Apple")) {
return true;
}
}
return false;
};
Predicate<List<Fruit>> containsApple = list -> list.contains(new Fruit("Apple"));
建议熟悉 Stream(如 for 遍历集合)及其表达能力。
Predicate<List<Fruit>> containsApple = list ->
list.stream()
.anyMatch(fr -> fr.getFruit().equals("Apple"));
在 Java 文档中给出 -
Modifier and Type Method and Description
static <T> Predicate<T> isEqual(Object targetRef)
Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
在https://www.geeksforgeeks.org/java-8-predicate-with-examples/
给出-
isEqual(Object targetRef) : Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
static Predicate isEqual(Object targetRef) Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object). T : the type of arguments to the predicate Parameters: targetRef : the object reference with which to compare for equality, which may be null Returns: a predicate that tests if two arguments are equal according to Objects.equals(Object, Object)
我无法理解这个 Objects.equals(Object, Object)
可能是什么
我写了下面的代码试试看-
Class 水果 -
Fruits.java
-
public class Fruits {
private String fruit;
public Fruits(String fruit) {
this.fruit = fruit;
}
public String getFruit() {
return fruit;
}
}
到这里,predicate的其他方法好像还挺容易理解的-
Predicate<List<Fruits>> containsApple = list -> {
boolean myReturn = false;
Iterator<Fruits> iterator = list.iterator();
while (iterator.hasNext()) {
Fruits fruits = iterator.next();
String fruit = fruits.getFruit();
if (fruit.equals("Apple")) {
myReturn = true;
break;
}
}
return myReturn;
};
Predicate<List<Fruits>> containsOrange = list -> {
boolean myReturn = false;
Iterator<Fruits> iterator = list.iterator();
while (iterator.hasNext()) {
Fruits fruits = iterator.next();
String fruit = fruits.getFruit();
if (fruit.equals("Orange")) {
myReturn = true;
break;
}
}
return myReturn;
};
Predicate<List<Fruits>> containsAppleAndOrange = list -> {
return containsApple.and(containsOrange).test(list);
};
Predicate<List<Fruits>> containsAppleOrRange = list -> {
return containsApple.or(containsOrange).test(list);
};
Predicate<List<Fruits>> notContainsApple = list -> {
return containsApple.negate().test(list);
};
Predicate<List<Fruits>> notContainsOrange = list -> {
return containsOrange.negate().test(list);
};
Predicate<List<Fruits>> notContainsAppleAndOrange = list -> {
return containsAppleAndOrange.negate().test(list);
};
Predicate<List<Fruits>> notContainsAppleOrOrange = list -> {
return containsAppleOrRange.negate().test(list);
};
这里我用下面的数据进行测试-
List<Fruits> list1 = new ArrayList<>(List.of(
new Fruits("Apple"),
new Fruits("Orange"),
new Fruits("Mango"),
new Fruits("Banana")
));
List<Fruits> list2 = new ArrayList<>(List.of(
new Fruits("Apple"),
new Fruits("Mango"),
new Fruits("Banana"),
new Fruits("Berry")
));
List<Fruits> list3 = new ArrayList<>(List.of(
new Fruits("Orange"),
new Fruits("Mango"),
new Fruits("Banana"),
new Fruits("Berry")
));
结果符合预期。
但是我完全无法理解如何实现 isEqual()
方法 -
要查看两个参数是否相等,我创建了另一个谓词 -
redicate<List<Fruits>> containsApple2 = list -> {
boolean myReturn = false;
Iterator<Fruits> iterator = list.iterator();
while (iterator.hasNext()) {
Fruits fruits = iterator.next();
String fruit = fruits.getFruit();
if (fruit.equals("Apple")) {
myReturn = true;
break;
}
}
return myReturn;
};
我尝试类似(不明白为什么)-
System.out.println(Predicate.isEqual(containsApple).test(list1));
输出 - false
现在这里发生了什么?
System.out.println(Predicate.isEqual(containsApple2).test(containsApple));
输出 - false
现在又发生了什么事?
那么,这个isEqual
方法具体怎么用呢?
Predicate.isEqual
是一个工厂方法,它创建谓词来测试给定的事物是否等于传入的参数。
Predicate.isEqual(containsApple)
创建一个 Predicate<Predicate<List<Fruits>>>
来测试给定的事物是否等于 containsApple
。但是,由于 containsApple
指的是从 lambda 创建的实例,并且对于从 lambda 表达式创建的实例的相等性并没有太多保证(参见 JLS),所以关于结果没有什么可以说的在上面调用 test
。 lambda 实例的 类 可能实现也可能不实现 equals
,并且 containsApple
可能与 containsApple2
是同一实例,也可能不同,具体取决于实现。
而不是比较 lambda 实例,使用 Predicate.isEqual
的典型示例是:
Fruits apple = new Fruits("Apple");
Predicate<Fruits> isApple = Predicate.isEqual(apple);
// rather than this slightly longer version:
// Predicate<Fruits> isApple = x -> Objects.equals(x, apple);
然后你可以将 isApple
传递给其他需要 Predicate
s 的方法,and/or 调用 test
就可以了。 isApple.test(apple)
为真,isApple.test(new Fruits("something else"))
为假。我还建议您在 Fruits
.
equals
和 hashCode
请注意,我们通常使用谓词来测试单个对象,而不是事物列表(集合)。我们会将这些谓词传递给其他方法(例如 Stream.filter
),并让 它们 进行过滤。例如,要过滤列表以获取所有苹果:
List<Fruits> apples = fruitsList.stream()
.filter(Predicate.isEqual(apple)).toList();
这里 class 水果应该用单数。
首先你必须建立水果的平等。如果您希望它存储在 HashMap 或 HashSet 中,hashCode
实现也很重要。
public class Fruit {
private final String fruit; // Or name.
public Fruit(String fruit) {
this.fruit = fruit;
}
public String getFruit() {
return fruit;
}
@Override
public boolean equals(Object other) {
return other instanceOf Fruit && ((Fruit) other).fruit.equals(fruit);
}
@Override
public int hashCode() {
return fruit.hashCode();
}
}
迭代器 class 相当陈旧,它的主要优点是您可以遍历并仍然使用 iterator.remove()
删除元素,这在 - statefull - for ( ConcurrentModificationException).
Predicate<List<Fruit>> containsApple = list -> {
for (Fruit fruit: list) {
if (fruit.getFruit().equals("Apple")) {
return true;
}
}
return false;
};
Predicate<List<Fruit>> containsApple = list -> list.contains(new Fruit("Apple"));
建议熟悉 Stream(如 for 遍历集合)及其表达能力。
Predicate<List<Fruit>> containsApple = list ->
list.stream()
.anyMatch(fr -> fr.getFruit().equals("Apple"));