我们有对象 A 类型,它包含一个对象数组 B 类型,而不是包含对象数组 C 类型,如示例中所示:
/* sample structure that ends with 4 instances of C with ids.100,200,100,200 */
private class A{
int id;
A(int id) {
this.id = id;
}
B[] b = new B[]{new B(10), new B(20) };
}
private class B{
int id;
B(int id) {
this.id = id;
}
C[] c = new C[]{new C(100), new C(200) };
}
private class C{
int id;
C(int id) {
this.id = id;
}
public String toString(){
return ""+id;
}
}
如果我们尝试获得所有不同的 c.id(100,200),第一种方法可能是
HashSet<Integer> distinctIdsOfC = new HashSet<Integer>();
for (B bbb: a.b){
for (C ccc: bbb.c){
distinctIdsOfC.add(ccc.id);
}
}
(结果如预期为 100、200)
还有我的第一个 attepmt 与 lambda
List<C> a6 = Arrays.asList(a.b).stream().map(jaja -> Arrays.asList(jaja.c)).flatMap(List::stream).collect(Collectors.toList());
a6.stream().map(x->x.id).distinct().forEach(System.out::println);
(结果再次如预期的那样是 100、200)
最后是问题。有更好的替代λ吗?
/* Complete source sample to test */
package test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
public class Test {
public static void main(String[] args) {
Test t = new Test();
t.haz();
}
private void haz() {
A a = new A(1);
HashSet<Integer> distinctIdsOfC = new HashSet<Integer>();
for (B bbb : a.b) {
for (C ccc : bbb.c) {
distinctIdsOfC.add(ccc.id);
}
}
System.out.println("with for-loop" + distinctIdsOfC.toString());
System.out.println("with lambda");
List<C> a6 = Arrays.asList(a.b).stream().map(jaja -> Arrays.asList(jaja.c)).flatMap(List::stream)
.collect(Collectors.toList());
a6.stream().map(x -> x.id).distinct().forEach(System.out::println);
}
private class A {
int id;
A(int id) {
this.id = id;
}
B[] b = new B[] { new B(10), new B(20) };
}
private class B {
int id;
B(int id) {
this.id = id;
}
C[] c = new C[] { new C(100), new C(200) };
}
private class C {
int id;
C(int id) {
this.id = id;
}
public String toString() {
return "" + id;
}
}
}
好的,我认为我们有很多选择,但是:
1) 在 C 类中实现 equlas/hashCode,然后:
Arrays.stream(a.b)
.map(s -> s.c)
.flatMap(Arrays::stream)
.distinct()
.forEach(System.out::println)
但是,如果您无法添加哈希代码/等于:
2) 创建过滤方法(按类字段区分):
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object,Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
然后像这样写 lambda:
Arrays.asList(a.b).stream()
.map(jaja -> Arrays.asList(jaja.c))
.flatMap(List::stream)
.filter(distinctByKey(s -> s.id))
.forEach(System.out::println);
有了注释中的所有有价值的信息,我们正在寻找不同的 id 值,而不是分散的对象并试图让它更简单,以 lambda 结尾。
/* proposed lambda */
System.out.println("with lambda");
Set<Integer> a7 = Arrays.stream(a.b).flatMap(jaja-> Arrays.stream(jaja.c).map(jeje->jeje.id)).collect(Collectors.toSet());
System.out.println("with lambda set a7");
a7.stream().forEach(System.out::println);
这避免了中间不使用列表,避免了明显,并且更短更清晰。