如何比较两组对象不使用比较器和流覆盖 equals/hashCode
How to compare two Sets of objects Not overriding equals/hashCode with Comparator and Streams
我有两个 Set
,如下所示:
Set<Book> s1 = createBooks();
Set<Book> s2 = createBooks(); // or any set of values
和这个方法:
private Set<Book> createBooks() {
List<String> name = Arrays.asList("book 1", "book 2", "book 3");
List<BookType> type = Arrays.asList(BookType.TYPEONE, BookType.TYPETWO);
Set<Book> listOfBooks = new HashSet<>();
for(int i=0; i<2; i++) {
Book book = new Book();
book.setName(name.get(i));
book.setType(type.get(i));
listOfBooks.add(books);
}
return listOfBooks;
}
还有这个class:
Class Book {
private String name;
private BookType type;
//here is getter and setter ...
}
我确实实现了这个 Comparator
,但我不确定它是否正常工作:
Comparator<Book> comparingBooks = (o1, o2) -> {
if (o1.getName().compareTo(o2.getName()) == 0) {
return o1.getType().compareTo(o2.getType());
}
return o1.getName().compareTo(o2.getName());
};
//I did try this implementation but am not sure it's working as well:
//Comparator<Book> comparingBooks = Comparator.comparing((Book b)->b.getNName())
.thenComparing(b->b.getType());
期望结果为true
时的集合示例:
s1 = (new Book("book 1", BookType.ONE), new Book("book 2", BookType.TWO));
s2 = (new Book("book 1", BookType.ONE), new Book("book 2", BookType.TWO));
期望结果为false
时的集合示例:
s1 = (new Book("book 1", BookType.ONE), new Book("book 2", BookType.TWO));
s2 = (new Book("book 1", BookType.ONE), new Book("book 2", BookType.ONE));
我需要将这些集合与以下内容进行比较:
// this flag should validate any difference of Name
// and Type by returning true,
// if both Sets have exactly the same objects,
// it should return false.
boolean compareBooks = s1.stream().anyMatch(a -> s2.stream().anyMatch(b -> comparingBooks.compare(a, b) != 0));
我也试过了,但没有用,而且总是 return 相同的值:
boolean compareBooks = SetUtils.isEqualSet(s1, s2);
我没有 equals 和 hashcode 实现,因此无法实现。
有没有其他方法可以用 java 8 和比较器来检查和比较这些集合?
您可以使用比较器创建一个 TreeSet
来实现相等而不是 equals()
:
Set<Books> listOfBooks = new TreeSet<>(comparingBooks);
现在您可以使用标准的收集方法来比较集合:
boolean compareBooks = !Collections.disjoint(s1, s2);
比较器修复
为了在这种情况下创建 Comparator
,您需要显式提供通用类型信息,例如:<Book, String>comparing()
,其中 Book
和 String
是Comparator.comparing()
期望作为参数的 Function
的参数类型和 return 类型。
如果没有显式声明,编译器没有足够的数据来确定变量 book
的类型,在 comparing()
和 thenComparing()
中,其类型将被推断为 Object
.
Comparator<Book> comparingBooks =
Comparator.<Book, String>comparing(book -> book.getName())
.thenComparing(book -> book.getType());
如果只使用了一个静态方法,book
变量的类型将是编译器根据语言环境变量的 类型正确推断为 Book
Comparator<Book> comparingBooks
.
两种方法 lambda 表达式都可以替换为方法引用:
Comparator<Book> comparingBooks =
Comparator.<Book, String>comparing(Book::getName)
.thenComparing(Book::getType);
for information on the syntax of generic methods, take a look at this tutorial
for more information on how to build comparators with Java 8 methods take a look at this tutorial
流
should validate any difference of Name and Type by returning true, if both Sets have exactly the same objects, it should return false.
Stream s1.stream().anyMatch(a -> s2.stream().anyMatch(b -> ...))
当前正在检查第一组 s1
中是否有一个元素与 s2 中的 ANY 元素不同。 IE。对于在 s1 中遇到的第一个没有匹配元素的元素,嵌套的 anyMatch()
将 return true
在 s2。经过Book("book 1", BookType.ONE)
(s1)与Book("book 2", BookType.TWO)
(s2 ) anyMatch()
由 returning true
终止。并包含 anyMatch()
操作传播此结果。
与第二个例子完全一样。 相同的一对元素不同,虽然你改变了类型,名称不相等。结果是 true
.
注:
- 按照惯例 类 通常用 单数名词 命名,即
Book
(不是 Books) , Event
, Person
, 等等
- 根据经验,如果您的对象打算与集合一起使用,则它们必须实现
equals/hashCode
契约,您的要求非常不寻常。
我有两个 Set
,如下所示:
Set<Book> s1 = createBooks();
Set<Book> s2 = createBooks(); // or any set of values
和这个方法:
private Set<Book> createBooks() {
List<String> name = Arrays.asList("book 1", "book 2", "book 3");
List<BookType> type = Arrays.asList(BookType.TYPEONE, BookType.TYPETWO);
Set<Book> listOfBooks = new HashSet<>();
for(int i=0; i<2; i++) {
Book book = new Book();
book.setName(name.get(i));
book.setType(type.get(i));
listOfBooks.add(books);
}
return listOfBooks;
}
还有这个class:
Class Book {
private String name;
private BookType type;
//here is getter and setter ...
}
我确实实现了这个 Comparator
,但我不确定它是否正常工作:
Comparator<Book> comparingBooks = (o1, o2) -> {
if (o1.getName().compareTo(o2.getName()) == 0) {
return o1.getType().compareTo(o2.getType());
}
return o1.getName().compareTo(o2.getName());
};
//I did try this implementation but am not sure it's working as well:
//Comparator<Book> comparingBooks = Comparator.comparing((Book b)->b.getNName())
.thenComparing(b->b.getType());
期望结果为true
时的集合示例:
s1 = (new Book("book 1", BookType.ONE), new Book("book 2", BookType.TWO));
s2 = (new Book("book 1", BookType.ONE), new Book("book 2", BookType.TWO));
期望结果为false
时的集合示例:
s1 = (new Book("book 1", BookType.ONE), new Book("book 2", BookType.TWO));
s2 = (new Book("book 1", BookType.ONE), new Book("book 2", BookType.ONE));
我需要将这些集合与以下内容进行比较:
// this flag should validate any difference of Name
// and Type by returning true,
// if both Sets have exactly the same objects,
// it should return false.
boolean compareBooks = s1.stream().anyMatch(a -> s2.stream().anyMatch(b -> comparingBooks.compare(a, b) != 0));
我也试过了,但没有用,而且总是 return 相同的值:
boolean compareBooks = SetUtils.isEqualSet(s1, s2);
我没有 equals 和 hashcode 实现,因此无法实现。
有没有其他方法可以用 java 8 和比较器来检查和比较这些集合?
您可以使用比较器创建一个 TreeSet
来实现相等而不是 equals()
:
Set<Books> listOfBooks = new TreeSet<>(comparingBooks);
现在您可以使用标准的收集方法来比较集合:
boolean compareBooks = !Collections.disjoint(s1, s2);
比较器修复
为了在这种情况下创建 Comparator
,您需要显式提供通用类型信息,例如:<Book, String>comparing()
,其中 Book
和 String
是Comparator.comparing()
期望作为参数的 Function
的参数类型和 return 类型。
如果没有显式声明,编译器没有足够的数据来确定变量 book
的类型,在 comparing()
和 thenComparing()
中,其类型将被推断为 Object
.
Comparator<Book> comparingBooks =
Comparator.<Book, String>comparing(book -> book.getName())
.thenComparing(book -> book.getType());
如果只使用了一个静态方法,book
变量的类型将是编译器根据语言环境变量的 类型正确推断为 Book
Comparator<Book> comparingBooks
.
两种方法 lambda 表达式都可以替换为方法引用:
Comparator<Book> comparingBooks =
Comparator.<Book, String>comparing(Book::getName)
.thenComparing(Book::getType);
for information on the syntax of generic methods, take a look at this tutorial
for more information on how to build comparators with Java 8 methods take a look at this tutorial
流
should validate any difference of Name and Type by returning true, if both Sets have exactly the same objects, it should return false.
Stream s1.stream().anyMatch(a -> s2.stream().anyMatch(b -> ...))
当前正在检查第一组 s1
中是否有一个元素与 s2 中的 ANY 元素不同。 IE。对于在 s1 中遇到的第一个没有匹配元素的元素,嵌套的 anyMatch()
将 return true
在 s2。经过Book("book 1", BookType.ONE)
(s1)与Book("book 2", BookType.TWO)
(s2 ) anyMatch()
由 returning true
终止。并包含 anyMatch()
操作传播此结果。
与第二个例子完全一样。 相同的一对元素不同,虽然你改变了类型,名称不相等。结果是 true
.
注:
- 按照惯例 类 通常用 单数名词 命名,即
Book
(不是 Books) ,Event
,Person
, 等等 - 根据经验,如果您的对象打算与集合一起使用,则它们必须实现
equals/hashCode
契约,您的要求非常不寻常。