使用java流将列表转换为映射

使用java流将列表转换为映射,java,java-stream,Java,Java Stream,我在代码中重复了以下模式: class X<T, V> { V doTransform(T t) { return null; // dummy implementation } Map<T, V> transform(List<T> item) { return item.stream().map(x->new AbstractMap.SimpleEntry<>(x, doTrans

我在代码中重复了以下模式:

class X<T, V>
{
    V doTransform(T t) {
        return null; // dummy implementation
    }

    Map<T, V> transform(List<T> item) {
        return item.stream().map(x->new AbstractMap.SimpleEntry<>(x, doTransform(x))).collect(toMap(x->x.getKey(), x->x.getValue()));
    }
}
X类
{
V点变换(T){
返回null;//伪实现
}
映射变换(列表项){
return item.stream().map(x->newAbstractMap.SimpleEntry(x,doTransform(x)).collect(toMap(x->x.getKey(),x->x.getValue());
}
}
需要使用AbstractMap.SimpleEntry是混乱和笨拙的。LINQ对匿名类型的使用更加优雅

有没有一种更简单的方法可以使用流来实现这一点


提前发送Thx。

您可以在值映射器中调用
doTransform

Map<T, V> transform(List<T> item) {
    return item.stream().collect(toMap(x -> x, x -> doTransform(x)));
}
映射变换(列表项){
return item.stream().collect(toMap(x->x,x->doTransform(x));
}

您可以在值映射器中调用
doTransform

Map<T, V> transform(List<T> item) {
    return item.stream().collect(toMap(x -> x, x -> doTransform(x)));
}
映射变换(列表项){
return item.stream().collect(toMap(x->x,x->doTransform(x));
}

不幸的是,Java没有完全等同于C#的匿名类型

在这种特定情况下,您不需要@Jorn Vernee建议的中间
map
操作。相反,您可以在
toMap
收集器中执行键和值提取

然而,当你认为你需要C#的匿名类型时,你可以考虑:

  • (可能并不总是您想要的,这取决于您的用例)
  • Arrays.asList(…)
    List.of(…)
    (可能并不总是您想要的,具体取决于您的用例)
  • 阵列(可能并不总是您想要的,取决于您的用例)
  • 最后,如果您真的需要映射到可以包含两种不同类型元素的对象,那么我将坚持使用
    AbstractMap.SimpleEntry

    也就是说,您当前的示例可以简化为:

    Map<T, V> transform(List<T> items) {
        return items.stream().collect(toMap(Function.identity(),this::doTransform));
    }
    
    映射变换(列表项){
    return items.stream().collect(toMap(Function.identity(),this::doTransform));
    }
    
    不幸的是,Java没有完全等同于C#的匿名类型

    在这种特定情况下,您不需要@Jorn Vernee建议的中间
    map
    操作。相反,您可以在
    toMap
    收集器中执行键和值提取

    然而,当你认为你需要C#的匿名类型时,你可以考虑:

  • (可能并不总是您想要的,这取决于您的用例)
  • Arrays.asList(…)
    List.of(…)
    (可能并不总是您想要的,具体取决于您的用例)
  • 阵列(可能并不总是您想要的,取决于您的用例)
  • 最后,如果您真的需要映射到可以包含两种不同类型元素的对象,那么我将坚持使用
    AbstractMap.SimpleEntry

    也就是说,您当前的示例可以简化为:

    Map<T, V> transform(List<T> items) {
        return items.stream().collect(toMap(Function.identity(),this::doTransform));
    }
    
    映射变换(列表项){
    return items.stream().collect(toMap(Function.identity(),this::doTransform));
    }
    
    在此特定示例中,根本不需要执行中间存储:

    Map<T, V> transform(List<T> item) {
        return item.stream().collect(toMap(x -> x, x -> doTransform(x)));
    }
    
    但效率较低。它是一个内部类,捕获对周围
    this
    的引用,也捕获
    x
    ,因此您有两个字段,
    t
    和用于捕获
    x
    的合成字段

    后者可以通过使用一种方法来规避,例如

    Map<T, V> transform(List<T> item) {
        return item.stream()
                   .map(x -> new Object(){ T getKey() { return x; } V v = doTransform(x); })
                   .collect(toMap(x -> x.getKey(), x -> x.v));
    }
    
    映射变换(列表项){
    returnitem.stream()
    .map(x->new Object(){T getKey(){return x;}V V=doTransform(x);})
    .collect(toMap(x->x.getKey(),x->x.v));
    }
    
    但这并没有增加可读性

    唯一真正的匿名类型是为lambda表达式生成的类型,可用于通过高阶函数存储信息:

    Map<T, V> transform(List<T> item) {
        return item.stream()
                   .map(x -> capture(x, doTransform(x)))
                   .collect(HashMap::new, (m,f) -> f.accept(m::put), HashMap::putAll);
    }
    
    映射变换(列表项){
    returnitem.stream()
    .map(x->capture(x,doTransform(x)))
    .collect(HashMap::new,(m,f)->f.accept(m::put),HashMap::putAll);
    }
    
    公共静态消费者捕获(A、B){
    返回f->f.接受(a,b);
    }
    

    但是,如果您在更复杂的场景中尝试这种方法,您很快就会发现Java类型系统的局限性(它仍然不是函数式编程语言)。

    在这个特定示例中,根本不需要执行中间存储:

    Map<T, V> transform(List<T> item) {
        return item.stream().collect(toMap(x -> x, x -> doTransform(x)));
    }
    
    但效率较低。它是一个内部类,捕获对周围
    this
    的引用,也捕获
    x
    ,因此您有两个字段,
    t
    和用于捕获
    x
    的合成字段

    后者可以通过使用一种方法来规避,例如

    Map<T, V> transform(List<T> item) {
        return item.stream()
                   .map(x -> new Object(){ T getKey() { return x; } V v = doTransform(x); })
                   .collect(toMap(x -> x.getKey(), x -> x.v));
    }
    
    映射变换(列表项){
    returnitem.stream()
    .map(x->new Object(){T getKey(){return x;}V V=doTransform(x);})
    .collect(toMap(x->x.getKey(),x->x.v));
    }
    
    但这并没有增加可读性

    唯一真正的匿名类型是为lambda表达式生成的类型,可用于通过高阶函数存储信息:

    Map<T, V> transform(List<T> item) {
        return item.stream()
                   .map(x -> capture(x, doTransform(x)))
                   .collect(HashMap::new, (m,f) -> f.accept(m::put), HashMap::putAll);
    }
    
    映射变换(列表项){
    returnitem.stream()
    .map(x->capture(x,doTransform(x)))
    .collect(HashMap::new,(m,f)->f.accept(m::put),HashMap::putAll);
    }
    
    公共静态消费者捕获(A、B){
    返回f->f.接受(a,b);
    }
    

    但是如果您在更复杂的场景中尝试这种方法,您很快就会发现Java类型系统的局限性(它仍然不是函数式编程语言)。

    Nice!,我的回答可能有点懒;)还有自Java 9以来的
    Map.entry()
    factory方法,它稍微短一点。很好!,我的回答可能有点懒;)还有自Java9以来的
    Map.entry()
    factory方法,它稍微短一点。