Java 8:比较不同类型列表的更有效的方法? [英] Java 8: More efficient way of comparing lists of different types?
问题描述
在单元测试中,我想验证两个列表是否包含相同的元素。要测试的列表是构建一个 Person
对象的列表,其中提取了 String
类型的一个字段。另一个列表包含 String
文字。
In a unit test, I want to verify that two lists contain the same elements. The list to test is build of a list of Person
objects, where one field of type String
is extracted. The other list contains String
literals.
通常会找到以下代码片段来完成此任务href =http://stackoverflow.com/questions/27641261/comparing-lists-of-different-types/27641329#27641329>此答案):
One often finds the following code snippet to accomplish this task (see this answer):
List<Person> people = getPeopleFromDatabasePseudoMethod();
List<String> expectedValues = Arrays.asList("john", "joe", "bill");
assertTrue(people.stream().map(person -> person.getName()).collect(Collectors.toList()).containsAll(expectedValues));
Person
class defiend as: / p>
The Person
class is defiend as:
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
// other getters and setters
}
在上面的示例中,使用Java 8技术将人员(或人员)列表转换为字符串列表,并以老式方式进行比较。
In the example above, the list of persons (or people) is transformed to a list of Strings using Java 8 techniques and the comparision is done in the old-fashioned way.
现在我想知道,如果有一个更直接或更有效的方式使用其他Java 8语句进行比较,例如 allMatch()
或一些谓词< T>
或其他。
Now I wonder, if there is a more direct or more efficient way of doing the comparison using other Java 8 statements, for example allMatch()
or some Predicate<T>
or something else.
推荐答案
你在评论中描述的内容。
Your question’s code does not reflect what you describe in the comments. In the comments you say that all names should be present and the size should match, in other words, only the order may be different.
您的代码是
List<Person> people = getPeopleFromDatabasePseudoMethod();
List<String> expectedValues = Arrays.asList("john", "joe", "bill");
assertTrue(people.stream().map(person -> person.getName())
.collect(Collectors.toList()).containsAll(expectedValues));
>,换句话说,允许重复。此外,使用 containsAll
组合两个 List
非常低效。如果你使用反映你的意图,即没有重复,不关心订单和有效的查找集合类型,更好的:
which lacks a test for the size of people
, in other words allows duplicates. Further, using containsAll
combining two List
s in very inefficient. It’s much better if you use a collection type which reflects you intention, i.e. has no duplicates, does not care about an order and has an efficient lookup:
Set<String> expectedNames=new HashSet<>(expectedValues);
assertTrue(people.stream().map(Person::getName)
.collect(Collectors.toSet()).equals(expectedNames));
使用此解决方案,您不需要手动测试大小,
with this solution you don’t need to test for the size manually, it is already implied that the sets have the same size if they match, only the order may be different.
有一个解决方案不需要收集 persons的名称
:
There is a solution which does not require collecting the names of persons
:
Set<String> expectedNames=new HashSet<>(expectedValues);
assertTrue(people.stream().allMatch(p->expectedNames.remove(p.getName()))
&& expectedNames.isEmpty());
但它仅适用于 expectedNames
临时集从静态预期名称集合中创建。一旦你决定用 Set
替换你的静态集合,第一个解决方案不需要临时集合,后者没有优势。
but it only works if expectedNames
is a temporary set created out of the static collection of expected names. As soon as you decide to replace your static collection by a Set
, the first solution doesn’t require a temporary set and the latter has no advantage over it.
这篇关于Java 8:比较不同类型列表的更有效的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!