切换对象之间的关联方向

And*_*bie 5 java java-8 java-stream

说我有一节课foo:

class foo {
    String someString;
    List<String> someList;
}
Run Code Online (Sandbox Code Playgroud)

如果我有一个列表foo,有没有办法让我创建一个新的列表/数组/什么是foo基本上someStringsomeList值重新映射?例如:

arr1: [
    foo {
        someString: 'test1',
        someList: ['a', 'b']
    },
    foo {
        someString: 'test2',
        someList: ['b', 'c']
    }
]
Run Code Online (Sandbox Code Playgroud)

会成为

arr2: [
    foo {
        someString: 'a',
        someList: ['test1']
    },
    foo {
        someString: 'b',
        someList: ['test1', 'test2']
    },
    foo {
        someString: 'c',
        someList: ['test2']
    },
]
Run Code Online (Sandbox Code Playgroud)

现在,我有一个嵌套循环,它迭代someList每个foo的每个元素,并将它们编译成一个映射,其中键是someList值,值是一组someString来自foos的someList值,其中存在值.然后执行条目集的映射,将其转换为新的foos,其中键和值作为构造函数参数传递.

Map<String, Set<String>> myMap;

for(foo f : arr1) {
    for(String s : f.someList) {
        Set<String> mySet = myMap.get(s);
        if(mySet == null) {
            myMap.put(s, new HashSet<String>(Arrays.asList(f.someString)));
        } else {
            mySet.add(f.someString);
        }
    }
}

List<String> myNewList = myMap.entrySet()
                              .stream()
                              .map(e -> 
                                    new foo(e.key, new ArrayList<String>(e.value)))
                              .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

它似乎工作正常,但它不是世界上最漂亮的,所以我想知道是否有另一种方法来做到这一点.

Fed*_*ner 3

首先使用地图翻转对象:

Map<String, Set<String>> map = new LinkedHashMap<>();
arr1.forEach(foo -> 
        foo.someList.forEach(s -> 
                map.computeIfAbsent(
                    s, 
                    k -> new LinkedHashSet<>())
                .add(foo.someString)));
Run Code Online (Sandbox Code Playgroud)

foo然后从地图创建对象:

List<foo> result = new ArrayList<>();
map.forEach((k, v) -> list.add(new foo(k, new ArrayList<>(v))));
Run Code Online (Sandbox Code Playgroud)

这假设您有适当的构造函数。