Java8Lambdas——类型c#的等价物

Java8Lambdas——类型c#的等价物,java,c#,java-8,lambda,Java,C#,Java 8,Lambda,我现在正在学习新的Java8特性,在C#world中只呆了4年,所以Lambda是我的首选。我现在正努力为C#的“OfType”方法找到一个等价物 我有一个列表myNodes,我想从中得到一个列表,其中Node是一个接口,SpecificNode正在实现它 在C#中,应该是 IList<INode> myNodes = new List<INodes>(){new SpecificNode(), new OtherNode()} IList<SpecificNode

我现在正在学习新的Java8特性,在C#world中只呆了4年,所以Lambda是我的首选。我现在正努力为C#的“OfType”方法找到一个等价物

我有一个列表myNodes,我想从中得到一个列表,其中Node是一个接口,SpecificNode正在实现它

在C#中,应该是

IList<INode> myNodes = new List<INodes>(){new SpecificNode(), new OtherNode()}
IList<SpecificNode> specificNodes = myNodes.OfType<SpecificNode>()
IList myNodes=new List(){new SpecificNode(),new OtherNode()}
IList specificNodes=myNodes.OfType()的

Java中的
.OfType()
方法与没有精确的匹配,但是您可以使用Java8的过滤功能:

IList<INode> myNodes = new ArrayList<INode>();
myNodes.add(new SpecificNode());
myNodes.add(new OtherNode());

List<SpecificNode> filteredList = myNodes.stream()
                                         .filter(x -> x instanceof SpecificNode)
                                         .map(n -> (SpecificNode) n)
                                         .collect(Collectors.toList());
IList myNodes=new ArrayList();
添加(新的SpecificNode());
添加(新的OtherNode());
List filteredList=myNodes.stream()
.filter(x->x SpecificNode实例)
.map(n->(SpecificNode)n)
.collect(Collectors.toList());
如果要获得显式强制转换,可以执行以下操作:

List<SpecificNode> filteredList = myNodes.stream()
                                             .filter(SpecificNode.class::isInstance)
                                             .map(SpecificNode.class::cast)
                                             .collect(Collectors.toList());
List filteredList=myNodes.stream()
.filter(SpecificNode.class::isInstance)
.map(SpecificNode.class::cast)
.collect(Collectors.toList());

您可以创建一个包含流管道的函数,从而减少其调用

    Function<List<INode>,List<SpecificNode>> ofSub =
       bl -> bl.stream()
               .filter(x -> x instanceof SpecificNode)
               .map(n -> (SpecificNode) n)
               .collect(Collectors.toList());

我也有同样的问题。这就是我想到的,但是由于java不做扩展方法(可能在10年后?),所以它是一种静态方法。这是在使用流API,尽管没有特定的原因必须这样做。同样的基本检查在带有预分配ArrayList的
for
循环中也可以正常工作

@SuppressWarnings("unchecked")
private static <T> List<T> ofType(Class<?> out, List<Object> list) {
    return list.stream().filter(x -> out.isAssignableFrom(x.getClass()))
               .map(x -> (T) x) // unchecked
               .collect(Collectors.toList());
}

// fyi this code uses "boon" library
List<Object> objlist = list("ABC", 3, "def", -30.39); 
puts("strings=", ofType(String.class, objlist));  // strings= [ABC, def] 
puts("integers=", ofType(Integer.class, objlist)); // integers= [3]
@SuppressWarnings(“未选中”)
类型的私有静态列表(类输出,列表){
return list.stream().filter(x->out.isAssignableFrom(x.getClass()))
.map(x->(T)x)//未选中
.collect(Collectors.toList());
}
//仅供参考,此代码使用“boon”库
列表对象列表=列表(“ABC”,3,“def”,-30.39);
puts(“strings=”,of type(String.class,objlist));//字符串=[ABC,def]
puts(“integers=”,of type(Integer.class,objlist));//整数=[3]
这是一个不使用流的版本。它的工作原理是一样的,但流的一些乐趣是。。。如果你喜欢的话,你也许可以将它们流式传输。除了像这样的帮手,我不觉得它很有用

private static <T> List<T> ofType(Class<?> out, List<Object> list) {
    List<T> outList = new ArrayList<T>(list.size());
    for(Object o : list) {
        if ( out.isAssignableFrom(o.getClass())) {
            outList.add((T)o);
        }
    }
    return outList;
}
类型的私有静态列表(类输出,列表){
List outList=newarraylist(List.size());
用于(对象o:列表){
if(out.isAssignableFrom(o.getClass())){
大纲图。添加((T)o);
}
}
返回最长时间;
}

不必先过滤流,然后将其映射到所需的目标类型,可以通过
flatMap
对流进行一次调用,也可以使用此小辅助函数:

private static <Target extends Base, Base> Function<Base, Stream<Target>> ofType(Class<Target> targetType) {
    return value -> targetType.isInstance(value) ? Stream.of(targetType.cast(value)) : Stream.empty();
}
flatMap
操作的帮助下,所有返回的流都可以连接起来


我认为单独的检查和强制转换更容易理解,执行起来可能更快,这只是一个单流操作的概念证明。

您只需要在过滤器和收集器之间有一个
.map(n->(SpecificNode)n)
。谢谢!即使整个构造比C#长得多,它也能工作,这真是一个遗憾;(@PetrOsipov,我几乎可以肯定它可以缩短。我会进一步研究。)肯定是一个选择。java中是否有c#的扩展方法的等价物?如果存在的话,使用它们可能更容易…尝试在语言Y中找到语言X的特征f通常不是最好的方法。除此之外,每种语言都提供(或多或少)正交函数集。试图塞满所有东西的语言都有超重的问题。@PetrOsipov:Java花了数年时间才赶上lambdas上的C#语言——如果有扩展方法的话,还需要数年时间。Java不能像C#那样快速扩展。这是最好的答案。不明白为什么它被低估了
private static <Target extends Base, Base> Function<Base, Stream<Target>> ofType(Class<Target> targetType) {
    return value -> targetType.isInstance(value) ? Stream.of(targetType.cast(value)) : Stream.empty();
}
Stream.of(1, 2, 3, "Hallo", 4, 5, "Welt")
    .flatMap(ofType(String.class))
    .forEach(System.out::println);