Java 在对象之间切换关联方向
假设我有一门课Java 在对象之间切换关联方向,java,java-8,java-stream,Java,Java 8,Java Stream,假设我有一门课foo: class foo { String someString; List<String> someList; } 将成为 arr2: [ foo { someString: 'a', someList: ['test1'] }, foo { someString: 'b', someList: ['test1', 'test2'] }, fo
foo
:
class foo {
String someString;
List<String> someList;
}
将成为
arr2: [
foo {
someString: 'a',
someList: ['test1']
},
foo {
someString: 'b',
someList: ['test1', 'test2']
},
foo {
someString: 'c',
someList: ['test2']
},
]
现在,我有一个嵌套循环,它迭代每个foo的someList
的每个元素,并将它们编译成一个映射,其中键是someList
值,值是一组someString
值,这些值来自存在someList
值的foo。然后对条目集进行映射,将其转换为新的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());
Map-myMap;
对于(foo-f:arr1){
for(字符串s:f.someList){
设置mySet=myMap.get;
if(mySet==null){
put(s,新的HashSet(Arrays.asList(f.someString));
}否则{
add(f.someString);
}
}
}
List myNewList=myMap.entrySet()
.stream()
.map(e->
新foo(e.key,新ArrayList(e.value)))
.collect(Collectors.toList());
它似乎工作得很好,但它不是世界上最漂亮的,所以我想知道是否有其他方法可以做到这一点。为什么不像这样在嵌套循环中创建foo对象呢
Map<String, foo> myMap;
for(foo f : arr1) {
for(String s : f.someList) {
foo myFoo= myMap.get(s);
if(mySet == null) {
myFoo= new foo(s, new ArrayList<String>);
myMap.put(s, myFoo);
}
myFoo.somelist.add(f.someString);
}
}
Map-myMap;
对于(foo-f:arr1){
for(字符串s:f.someList){
foo myFoo=myMap.get(s);
if(mySet==null){
myFoo=新foo(s,新数组列表);
myMap.put(s,myFoo);
}
myFoo.somelist.add(f.someString);
}
}
以下是带有Guava库的java 8示例:
private static Function<Foo,Set<Foo>> fooStream(final Map<String,Foo> map){
return foo -> foo.getSomeList().stream()
.map(createNewFoo(foo.getSomeString(),map)).collect(Collectors.toSet());
}
private static Function<String,Foo> createNewFoo(final String someString,final Map<String,Foo> map){
return s->{
if(Objects.nonNull(map.get(s))){
map.get(s).getSomeList().add(someString);
return map.get(s);
}
return createNewFoo(s,someString,map);
};
}
private static Foo createNewFoo(final String someListValue , final String someString,final Map<String,Foo> map){
final Foo foo = new Foo(someListValue,Lists.newArrayList(someString));
map.put(someListValue,foo);
return foo;
}
私有静态函数fooStream(最终映射){
返回foo->foo.getSomeList().stream()
.map(createNewFoo(foo.getSomeString(),map)).collect(Collectors.toSet());
}
私有静态函数createNewFoo(最终字符串someString,最终映射){
返回s->{
if(Objects.nonNull(map.get))){
map.get.getSomeList().add(someString);
返回地图。获取(s);
}
返回createNewFoo(s,someString,map);
};
}
私有静态Foo createNewFoo(最终字符串someListValue、最终字符串someString、最终映射){
final Foo Foo=new Foo(someListValue,Lists.newArrayList(someString));
map.put(someListValue,foo);
返回foo;
}
下面是如何在main方法中调用它:
final Map<String, Foo> myMap = Maps.newHashMap();
final Foo foo1 = new Foo("test1",Arrays.asList("A","B"));
final Foo foo2 = new Foo("test2",Arrays.asList("B","C"));
final List<Foo> foos = Arrays.asList(foo1,foo2);
final Set<Foo> fooSet = foos.stream()
.map(fooStream(myMap))
.flatMap(Set::stream).collect(Collectors.toSet());
final Map myMap=Maps.newHashMap();
final Foo foo1=新的Foo(“test1”,Arrays.asList(“A”,“B”);
final Foo foo2=新的Foo(“test2”,Arrays.asList(“B”,“C”);
最终列表foos=Arrays.asList(foo1,foo2);
最终集fooSet=foos.stream()
.map(fooStream(myMap))
.flatMap(Set::stream).collect(collector.toSet());
其中Foo类是:
public class Foo {
private String someString;
private List<String> someList;
public Foo(String someString, List<String> someList) {
this.someString = someString;
this.someList = someList;
}
//getters and setters
}
公共类Foo{
私有字符串someString;
私人名单;
public Foo(String-someString,List-someslist){
this.someString=someString;
this.someList=someList;
}
//接球手和接球手
}
首先使用贴图翻转对象:
Map<String, Set<String>> map = new LinkedHashMap<>();
arr1.forEach(foo ->
foo.someList.forEach(s ->
map.computeIfAbsent(
s,
k -> new LinkedHashSet<>())
.add(foo.someString)));
这假设您有适当的构造函数。基本上是在someList中重复。在理想情况下,我会将其切换为一个集合,但这是不可能的,因此我认为在最后将集合转换为列表要比每次遍历foo.someList要好。通常情况下,只需几点。1.您在
映射中的最终输出当前不是列表
,而是集合
。2.除非您最终创建自己的接口实现,否则集合的初始化将无法以这种方式工作。3.初始化Set mySet=myMap.get对于someList中的每个字符串,代码>对于您希望获得的输出也没有意义。在某些地方,示例是伪代码,实际执行方法相当冗长。可能应该在最初的问题中明确说明这一点。我的想法是RE3需要进行空检查,初始化集合可以避免从if和else中的map中检索。哦,我想我明白你的意思了。只需执行包含键检查,而不是实际的init。编辑示例以使用实际语法。只需添加以澄清,然后适当的构造函数将字符串的集
转换为对象中预期的列表
。这很好,谢谢!这可能是个愚蠢的问题。LinkedHashSet只是为了维持顺序,还是有其他理由使用它?@AndrewRobie只是为了维持插入顺序。
Map<String, Set<String>> map = new LinkedHashMap<>();
arr1.forEach(foo ->
foo.someList.forEach(s ->
map.computeIfAbsent(
s,
k -> new LinkedHashSet<>())
.add(foo.someString)));
List<foo> result = new ArrayList<>();
map.forEach((k, v) -> list.add(new foo(k, new ArrayList<>(v))));