Java8流和地图值得吗?

Java8流和地图值得吗?,java,functional-programming,java-8,java-stream,Java,Functional Programming,Java 8,Java Stream,感觉Java8流和映射函数非常冗长,它们并不是真正的改进。例如,我编写了一些代码,使用一个集合生成另一个修改过的集合: private List<DartField> getDartFields(Class<?> model) { List<DartField> fields = new ArrayList<>(); for (Field field : model.getDeclaredFields()) { if

感觉Java8流和映射函数非常冗长,它们并不是真正的改进。例如,我编写了一些代码,使用一个集合生成另一个修改过的集合:

private List<DartField> getDartFields(Class<?> model) {
    List<DartField> fields = new ArrayList<>();
    for (Field field : model.getDeclaredFields()) {
        if (!Modifier.isStatic(field.getModifiers())) {
            fields.add(DartField.getDartField(field));
        }
    }
    return fields;
}
私有列表getDartFields(类模型){
列表字段=新的ArrayList();
for(字段:model.getDeclaredFields()){
如果(!Modifier.isStatic(field.getModifiers())){
fields.add(DartField.getDartField(field));
}
}
返回字段;
}
这似乎是java 8流及其函数的理想用例,因此我将其改写为:

private List<DartField> getDartFields(Class<?> model) {
    return Arrays.asList(model.getDeclaredFields())
            .stream()
            .filter(field -> !Modifier.isStatic(field.getModifiers()))
            .map(field -> DartField.getDartField(field))
            .collect(Collectors.toList());
}
私有列表getDartFields(类模型){
返回Arrays.asList(model.getDeclaredFields())
.stream()
.filter(field->!Modifier.isStatic(field.getModifiers()))
.map(field->DartField.getDartField(field))
.collect(Collectors.toList());
}
但我不确定我是否更喜欢这个。它是236个字符,而普通样式的java是239个字符。它似乎没有多少可读性。很好,您不必声明
ArrayList
,但需要调用
.collect(collector.toList())
数组。asList
(取决于数据类型)并没有任何好处

像这样使用
.stream()
是否有一些实际的改进,我就是不明白,或者这只是一种有趣的方式,让任何不懂函数编程的同事陷入困境


我想如果我动态地传递filter或map lambdas,它会很有用,但如果您不需要这样做…

您可以以不同的方式编写它(不一定更好)

私有列表getDartFields(类模型){
返回流.of(model.getDeclaredFields())
.filter(field->!Modifier.isStatic(field.getModifiers()))
.map(DartField::getDartField)
.collect(Collectors.toList());
}
使用静态导入看起来像

private static List<DartField> getDartFields(Class<?> model) {
    return of(model.getDeclaredFields())
            .filter(field -> !isStatic(field.getModifiers()))
            .map(DartField::getDartField)
            .collect(toList());
}
私有静态列表getDartFields(类模型){
返回(model.getDeclaredFields())
.filter(字段->!isStatic(字段.getModifiers()))
.map(DartField::getDartField)
.collect(toList());
}
它似乎没有多少可读性

这通常是IMHO的情况。然而,我要说的是,在超过10%的情况下,它明显更好。像任何新功能一样,您可能会从一开始就过度使用它,直到您熟悉它并发现您使用它的数量达到了您满意的程度

像这样使用.stream()是否有一些我不知道的实际改进,或者这只是一种有趣的方式,让任何不懂函数式编程的同事陷入循环

我怀疑两者都有。如果您不懂函数式编程,它往往是只读代码。i、 你仍然可以理解它的功能,问题是你是否必须维护它

IMHO,值得鼓励开发人员学习函数式编程,因为它对如何构造代码有一些非常有用的想法,即使您不使用FP语法,您也会从中受益

如果Streams API在以前的构造中很有用,您就不用费心实现了

例如,假设您想按名称为字段编制索引

private static Map<String, DartField> getDartFields(Class<?> model) {
    return of(model.getDeclaredFields())
            .filter(field -> !isStatic(field.getModifiers()))
            .map(DartField::getDartField)
            .collect(groupingBy(f -> f.getName()));
}
私有静态映射getDartFields(类模型){
返回(model.getDeclaredFields())
.filter(字段->!isStatic(字段.getModifiers()))
.map(DartField::getDartField)
.collect(分组方式(f->f.getName());
}
在过去,您可能使用列表而不是映射,但是通过简化映射的组装,您可能会使用您真正应该经常使用的数据结构

现在让我们看看如果我们使用更多的线程是否会更快

private static Map<String, DartField> getDartFields(Class<?> model) {
    return of(model.getDeclaredFields()).parallel()
            .filter(field -> !isStatic(field.getModifiers()))
            .map(DartField::getDartField)
            .collect(groupingByConcurrent(f -> f.getName()));
}
私有静态映射getDartFields(类模型){
返回(model.getDeclaredFields()).parallel()
.filter(字段->!isStatic(字段.getModifiers()))
.map(DartField::getDartField)
.collect(groupingByConcurrent(f->f.getName());
}

看看这有多困难,当你发现它可能弊大于利时,把它改回来也很容易。

如果你特别地把你的用例限制在你所发布的内容上,那么基于流的习惯用法并不是更好。但是,如果您有兴趣了解Streams API的真正优势,请参阅以下几点:

  • 基于流的习惯用法可以并行化,而实际上您无需付出任何努力(这实际上是Java首先获得lambdas的最有力的原因)
  • 流是可组合的:您可以传递它们并添加管道阶段。这将大大有利于代码重用
  • 正如您已经指出的,您还可以传递lambdas:编写模板方法很容易,只需插入处理的一个方面
  • 一旦您熟悉了这个习惯用法,FP代码实际上更具可读性,因为它和what而不是how的关系更为密切。这种优势随着处理逻辑的复杂性而增加

我还要指出,可读性的差异更多地是一种历史产物,而不是习语的固有特性:如果开发人员从一开始就学习FP,并每天使用FP,那么这将是一种奇怪且难以理解的命令式习语。

如果你坚持要回到集合中,这是不值得的。但是,您错过了一个机会——考虑下面的内容,您应该看到使用流添加代码的灵活性和可组合性的地方:

private static final Predicate<Field> isStatic
        = field -> !Modifier.isStatic(field.getModifiers());

private Stream<Field> getDeclaredFields(Class<?> model) {
    return Stream.of(model.getDeclaredFields());
}

private Stream<Field> getStaticFields(Class<?> model) {
    return getDeclaredFields(model).filter(isStatic);
}

private Stream<DartField> getDartFields(Class<?> model) {
    return getStaticFields(model)
            .map(field -> DartField.getDartField(field));
}
私有静态最终谓词是静态的
=字段->!isStatic(field.getModifiers());
私有流getDeclaredFields(类模型){
返回Stream.of(model.getDeclaredFields());
}
私有流getStaticFields(类模型){
返回getDeclaredFields(model).filter(isStatic);
}
私有流getDartFields(类模型){
返回getStaticField
private static final Predicate<Field> isStatic
        = field -> !Modifier.isStatic(field.getModifiers());

private Stream<Field> getDeclaredFields(Class<?> model) {
    return Stream.of(model.getDeclaredFields());
}

private Stream<Field> getStaticFields(Class<?> model) {
    return getDeclaredFields(model).filter(isStatic);
}

private Stream<DartField> getDartFields(Class<?> model) {
    return getStaticFields(model)
            .map(field -> DartField.getDartField(field));
}
private Stream<DartField> getDartFields(Class<?> model) {
    return Stream.of(model.getDeclaredFields())
            .filter(field -> !Modifier.isStatic(field.getModifiers()))
            .map(field -> DartField.getDartField(field));
}
getDartFields(Foo.class).forEach(System.out::println);
private List<DartField> getDartFields(Class<?> model) {
    return List.list(model.getDeclaredFields())
        .filter(field -> !Modifier.isStatic(field.getModifiers()))
        .map(field -> DartField.getDartField(field))
        .toJavaList();
}
StreamEx.of(model.getDeclaredFields())
        .filter(field -> !Modifier.isStatic(field.getModifiers()))
        .map(DartField::getDartField)
        .toList();
List<DartField> fields = new ArrayList<>();
for (Field field : model.getDeclaredFields()) {
    if (!Modifier.isStatic(field.getModifiers())) {
        fields.add(DartField.getDartField(field));
    }
}
return fields;