Java 8:比较不同类型列表的更有效的方法? [英] Java 8: More efficient way of comparing lists of different types?

查看:156
本文介绍了Java 8:比较不同类型列表的更有效的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在单元测试中,我想验证两个列表是否包含相同的元素。要测试的列表是构建一个 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 Personclass 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 Lists 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆