这是在Java中进行函数式编程的正确方法吗?

时间:2014-01-12 21:39:07

标签: java coding-style functional-programming

我正试图改变我的思维方式,使其更具功能性。这是我试图更改为更具功能性的示例代码。

 List<Integer> numbers = Arrays.asList(1, 2 ,3, 4, 5, 6);

 ArrayList<Integer> multipledByTwo = new ArrayList<Integer>();

 for(Integer number : numbers) {
       multipledByTwo.add(number * 2);
 }

据我了解功能java,最简单的规则是没有共享状态。我是否正确理解这段代码是共享状态multipledByTwo。这是我的函数java版本。

class MultipleByTwoIteration {
    public static List<Integer> map(List<Integer> numbers) {
        ArrayList<Integer> multipledByTwo = new ArrayList<Integer>();
        for(Integer number : numbers) {
            multipledByTwo.add(multipleByTwo(number));
        }

        return multipledByTwo;
    }

    private static Integer multipleByTwo(Integer number) {
        return number * 2;
    }
}

所以我可以做到

List<Integer> numbers = Arrays.asList(1, 2 ,3, 4, 5, 6);
List<Integer> multipledByTwo = MultipleByTwoIteration.map(numbers);

我是否认为这更像是一种功能性思维方式?如果代码不起作用,我该如何改进?

感谢。

2 个答案:

答案 0 :(得分:3)

最好使用Guava(或类似番石榴)风格来实现这一点。您可以实现Function<From,To>接口,然后使用适当的实用程序类来应用实现,而不是每个具有知道如何迭代的类的方法。

以你的例子,在番石榴:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

List<Integer> multipliedByTwo = Lists.transform(numbers, new Function<Integer, Integer>(){
      @Override
      public Integer apply(Integer input) {
          return input * 2;
      }
  }

这种风格很可能很容易在Java 8中转换为lambda函数。

有一个很棒的article on functional idioms in Guava,还有其他示例和建议。

答案 1 :(得分:1)

我想它有点功能但不是很多。您的地图功能会知道它将使用的操作,例如;如果你想要一个功能版本的你没有使用Guava或Java 8我写的东西我建议这样:

public interface Function<S, T> {
    T apply(S in);
}

abstract class MappingClass<S, T> {
    protected List<T> map(List<S> list, Function<S, T> fun) {
        List<T> result = new ArrayList<T>();
        for(T item : list) {
            result.add(fun.apply(item));
        }
    }
}

class MultipleByTwoIteration extends MappingClass {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2 ,3, 4, 5, 6);

        List<Integer> multipledByTwo = map(numbers, 
                new Function<Integer, Integer>() {
            public Integer apply(Integer in) {
                return in * 2;
            }
        });
    }
}

这是Java 8或Guava中添加的内容的一部分,但是手动完成。 map函数不知道它正在做什么,除了它正在对列表中的每个元素执行它。传递的函数不知道使用它的上下文。因此,它可以在其他上下文中使用,而无需修改除main函数之外的任何内容。

修改 仅供参考,在Java 8中也可以这样:

class MultipleByTwoIteration extends MappingClass {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2 ,3, 4, 5, 6);

        List<Integer> multipledByTwo =
            numbers.stream().map(x -> x * 2).collect(Collectors.toList());
    }
}

将提供Function接口,map函数以及用于创建匿名函数的更短语法(请参阅那里的x -> x * 2?)等。