假设我有3个类(强烈减少):
public interface Base
{
String getType();
}
public class Object1 implements Base
{
String getType() { ... };
long getSerialNr() { ... };
}
public class Object2 implements Base
{
String getType() { ... };
long getPartNr() { ... };
}
我如何(使用Java 8流)使用条件转换将List<Base>
转换为List<Long>
?我从这开始:
List<Long> result = baseList.stream().filter(Objects::nonNull)
.filter(Object1.class::isInstance)
.map(Object1.class::cast)
.map(o -> o.getSerialNr())
.collect(Collectors.toList());
...但是如何整合第二种情况,其中元素是Object2
的实例,我想返回getPartNr
?
答案 0 :(得分:3)
假设类的数量可能增长,您可能必须将类型的映射抽象为property:
static Map<Predicate<Base>,Function<Base,Long>> ACCESSORS;
static {
Map<Predicate<Base>,Function<Base,Long>> m=new HashMap<>();
m.put(Object1.class::isInstance, base -> ((Object1)base).getSerialNr());
m.put(Object2.class::isInstance, base -> ((Object2)base).getPartNr());
ACCESSORS=Collections.unmodifiableMap(m);
}
static Stream<Long> get(Base b) {
return ACCESSORS.entrySet().stream()
.filter(e -> e.getKey().test(b))
.map(e -> e.getValue().apply(b));
}
get
方法假定谓词是互斥的,在测试这些非interface
类型时就是这种情况。
然后,您可以像:
一样使用它List<Long> result = baseList.stream()
.flatMap(YourClass::get)
.collect(Collectors.toList());
您还可以内联get
方法,但这并没有提高可读性:
List<Long> result = baseList.stream()
.flatMap(b -> ACCESSORS.entrySet().stream()
.filter(e -> e.getKey().test(b))
.map(e -> e.getValue().apply(b)))
.collect(Collectors.toList());
答案 1 :(得分:2)
首先,如果不存在所有类应该实现的公共方法,那么接口Base中没有任何意义。如果你想这样做那么它就不会很好。您应该将代码更改为以下应该可以解决的问题:
List<Long> aList = baseList.stream().filter((Objects::nonNull)
.filter(obj->(obj instanceof Object1 || obj instanceof Object2))
.map(num-> (num instanceof Object1) ? ((Object1) num).getPratNr() : ((Object2) num).getPratNr())
.collect(Collectors.toList());
答案 2 :(得分:1)
您可以尝试按照其元素类对baseList进行分组。
public class MyTest {
@Test
public void java8_listbase_to_listlong_conditional_cast() {
List<Base> baseList = new ArrayList<>();
baseList.add(new Object1());
baseList.add(new Object2());
Map<?, List<Base>> group = baseList.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(key -> key.getClass()));
Stream<Long> object1stream = group.get(Object1.class)
.stream()
.map(Object1.class::cast)
.map(Object1::getSerialNr);
Stream<Long> object2stream = group.get(Object2.class)
.stream()
.map(Object2.class::cast)
.map(Object2::getPartNr);
List<Long> longList = Stream.concat(object1stream, object2stream).collect(Collectors.toList());
assertArrayEquals(new Long[] {0l, 1l}, longList.toArray());
}
public interface Base {
}
public class Object1 implements Base {
long getSerialNr() { return 0L; };
}
public class Object2 implements Base {
long getPartNr() { return 1L; };
}
}