如何将多个列表与流和lambdas组合在一起,指示存在重复的位置

时间:2016-06-08 17:54:42

标签: lambda java-8 java-stream

我正在尝试使用流和lambda将多个集合缩减为单个集合。但是我需要指出重复命中的位置。

基本上我有以下情况:

客户(所有人)的集合1

Person 1 (Tom)
Person 2 (Bob)
Person 3 (Joe)

前景集合2

Person 1 (Mike)
Person 2 (Wilbur)
Person 3 (Joe)

员工收集3

Person 1 (Mike)
Person 2 (Tony)
Person 3 (Sue)
Person 4 (Joe)

我想将这个集合转换为包含一个我可以使用Map做的新字段 - 我迷失了它实际上是如何压扁它以便最终结果将是这样的

集合

Person 1 (Tom, "Customer")
Person 2 (Bob, "Customer")
Person 3 (Joe, "Customer, Prospect, Employee")
Person 4 (Mike, "Prospect, Employee")
Person 5 (Wilbur, "Prospect")
Person 6 (Tony, "Employee")
Person 7 (Sue, "Employee")  

我只是计划创建一个字符串值来直观地表示它们属于哪个区域。

谢谢!

[编辑]

根据以下建议,我能够以这种方式测试解决方案......

class TestOutFlatMap {     public void test(){

    Map<String, Collection<Person>> map = new HashMap<>();

    Collection<Person> p1 = new ArrayList<>();
    p1.add(new Person("Mike"));
    p1.add(new Person("Joe"));
    p1.add(new Person("Tony"));

    Collection<Person> p2 = new ArrayList<>();
    p1.add(new Person("Wilbur"));
    p1.add(new Person("Joe"));
    p1.add(new Person("Molly"));

    Collection<Person> p3 = new ArrayList<>();
    p1.add(new Person("Wilbur"));
    p1.add(new Person("Joe"));
    p1.add(new Person("Bubba"));

    map.put("Customer", p1);
    map.put("Prospect", p2);
    map.put("Employee", p3);

    Map<Person, String> output = map
        .entrySet()
        .stream()
        .flatMap(t -> t.getValue().stream().map(g -> new Pair<>(t.getKey(), g)))
        .collect(Collectors.toMap(t -> t.getValue(), u -> u.getKey(), (x, y) -> x + ", " + y));

    output.keySet().stream().forEach(p -> {  
        System.out.println(p);
        System.out.println(output.get(p));
    });

}
class Person {
    String name;

    Person(String name){
        this.name = name;
    }

    public String toString () {return this.name;}

@Override
public int hashCode() {
    int hash = 5;
    return hash;
}

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    final Person other = (Person) obj;
    if (!Objects.equals(this.name, other.name)) {
        return false;
    }
    return true;
}

};

}

但是我的结果并不像预期的那样。他们返回如下:

Bubba 
Customer 
Molly 
Customer 
Wilbur Customer, Customer 
Tony Customer
Joe Customer, Customer, Customer 
Mike Customer

我没有看到它在哪里连接不正确。

2 个答案:

答案 0 :(得分:1)

由于您有多个不同类型的集合,因此每个集合都应该有一些标识符。因此,最好的方式是将您的输入表示为集合映射,其中映射的键表示集合的类型,例如Customer,Prospect和Employee。

现在,假设您有Map<String, Collection<Person>>,,则需要按集合的每个元素进行分组,并跟踪关联的密钥。为此,您需要使用flatmap。 以下代码应该有效:

    Map<String, Collection<Person>> map = new HashMap<>();
    map.put("Customer", ...);
    map.put("Prospect", ...;
    map.put("Employee", ...;

    Map<Person, String> output = map
        .entrySet()
        .stream()
        .flatMap(t -> t.getValue().stream().map(g -> new Pair<>(t.getKey(), g)))
        .collect(Collectors.toMap(
                t -> t.getValue(), u -> u.getKey(), (x, y) -> x + ", " + y));

请注意,对类使用的是javafx.util.Pair

答案 1 :(得分:1)

您可以尝试使用下游收集器进行分组,将组转换为字符串,如下所示:

        Map<Person, String> result = map
        .entrySet()
        .stream()
        .flatMap(e -> e.getValue().stream().map(v -> new AbstractMap.SimpleEntry<>(v,e.getKey())))
        .collect(
            Collectors.groupingBy(Map.Entry::getKey,         // group Map.Entry by key
                Collectors.mapping(Map.Entry::getValue,      // for each group, convert Map.Entry into the value 
                    Collectors.joining(","))));              // convert the values into a comma-delimited String

如果在同一类别键下可以找到两次相同的Person,并且您希望每个Person都有唯一的类别,那么您可以将每个组收集到{{1要使组元素唯一,然后使用SetSet转换为String,如下所示:

Collectors.collectingAndThen

通过以下设置,

        Map<Person, String> result = map
        .entrySet()
        .stream()
        .flatMap(e -> e.getValue().stream().map(v -> new AbstractMap.SimpleEntry<>(v,e.getKey())))
        .collect(Collectors.groupingBy(
                Map.Entry::getKey,
                Collectors.mapping(Map.Entry::getValue,
                        Collectors.collectingAndThen(
                                Collectors.toSet(), x -> String.join(",",x)))));

我得到 Map<String, Collection<Person>> map = new HashMap<>(); Person person1 = new Person("Person1"); Person person2 = new Person("Person2"); map.put("Customer", Arrays.asList(person1, person2)); map.put("Prospect", Arrays.asList(person1)); map.put("Employee", Arrays.asList(person2, person2));