简体   繁体   English

相当于Java 7中的map(来自haskell)

[英]Equivalent to map (from haskell) in Java 7

In Haskell there is a function called map , which takes a List of Type A and a function f , mapping values of type A to values of type B . 在Haskell中有一个名为map的函数,它接受类型A的List和函数f ,将类型A的值映射到类型B值。 It returns a list of type B , such that each element of the result list originates from a call of f to a value in the input list. 它返回类型B的列表,这样结果列表的每个元素都来自对输入列表中的值的f调用。

For example, given 例如,给定

  • a list m = ['a', 'b', 'c'] , 列表m = ['a', 'b', 'c']
  • and a function f = {'a' -> 1, 'b' -> 2, 'c' -> 3} , 和函数f = {'a' -> 1, 'b' -> 2, 'c' -> 3}
  • then map(m, f) = [1, 2, 3] . 然后map(m, f) = [1, 2, 3]

Is there a library, usable with Java 7, that offers something like the map function? 是否有一个可以与Java 7一起使用的库,它提供了类似map函数的东西? I already viewed apache CollectionUtils and found things like forAllDo and transform , but they don't allow retuning a collection of a completely different type. 我已经查看了apache CollectionUtils并发现了像forAllDotransform这样的东西,但它们不允许重新调整一个完全不同类型的集合。 Googling for other libraries failed for the same reason. 谷歌搜索其他库失败的原因相同。

To be clear: I know how to solve the problem by myself, but I strongly feel that there must already exist a good library that performs this task more generally. 要明确:我知道如何自己解决问题,但我强烈认为必须已经存在一个更好地执行此任务的好库。

Bonus question: Is there some equivalent to Haskell functors (ie move from collections to iterables) usable in Java 7? 额外的问题:在Java 7中是否有一些与Haskell仿函数相当的东西(即从集合转移到迭代)? Further explanation: Is there a map function which takes an Iterable<A> instead of Collection<A> and returns an Iterable<B> instead of Collection<B> (provided by a fitting function f )? 进一步说明:是否有一个map函数,它接受Iterable<A>而不是Collection<A>并返回Iterable<B>而不是Collection<B> (由拟合函数f )?

You are asking for Java 7 (with Java 8 it's easier): 您要求使用Java 7(使用Java 8更容易):

You can use Guava and there specifically FluentIterable 你可以使用Guava ,特别是FluentIterable

    final List<String> strings = Arrays.asList("a", "b", "c");
    final List<Integer> integers = FluentIterable
            .from(strings)
            .transform(new Function<String, Integer>() {
                @Nullable
                @Override
                public Integer apply(@Nullable String input) {
                    return input.equals("a") ? 1 : input.equals("b") ? 2 : input.equals("c") ? 3 : -1;
                }
            })
            .toList();

Bonus question: A collection is an iterable :-) 奖金问题:集合是可迭代的:-)

Functional transformations were added to Java 8 and they are not available for Java 7. For example, a map function that transforms a String to an integer looks like this Java 8 功能转换已添加到Java 8中,它们不适用于Java 7.例如,将String转换为整数的map函数类似于Java 8

List<String> list = Arrays.asList("1","2","3");
List<Integer> nums = list.stream().map(Integer::parseInt).collect(Collectors.toList());

Unlike Haskell, Java collections are strict, however Streams ( Java 8) are lifted ( ~ lazy). 与Haskell不同,Java集合是严格的,但是Streams (Java 8)被lifted (~lazy)。

There are libraries that support higher order functions for Java 7 like Guava . 有些库支持Java 7 higher order functions ,比如Guava Guava has a transform function that transforms T -> U, for ex: Guava有一个transform函数,可以转换T - > U,例如:

Collection<Integer> ints = Collections2.transform(list, new Function<String, Integer>() {
        @Override
        public Integer apply(String s) {
            return Integer.parseInt(s);
        }
    });

But as you can tell ,due to the lack of lambda expressions in Java 7, it doesn't look concise 但正如您所知,由于Java 7中缺少lambda表达式,它看起来并不简洁

You can write yourself an Iterator that takes a map object that does the transformation. 你可以自己编写一个Iterator ,它接受一个执行转换的map对象。

static class Transformer<F, T> implements Iterator<T> {

    final Iterator<F> source;
    final Map<F, T> map;

    public Transformer(Iterator<F> source, Map<F, T> map) {
        this.source = source;
        this.map = map;
    }

    @Override
    public boolean hasNext() {
        return source.hasNext();
    }

    @Override
    public T next() {
        return map.map(source.next());
    }

    public interface Map<F, T> {

        public T map(F f);
    }
}

private static final String[] numbers = {"Zero", "One", "Two", "Three", "Four", "Five"};

public void test() {
    List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5);
    Transformer t = new Transformer<>(ints.iterator(), new Transformer.Map<Integer, String>() {
        @Override
        public String map(Integer f) {
            return numbers[f];
        }

    });
    while (t.hasNext()) {
        System.out.println(t.next());
    }
}

You need use Stream APi from Java 8. Using official API you cann't using Stream APi in Java 7, but using: 您需要使用Java 8中的Stream APi。使用官方API,您不能在Java 7中使用Stream APi,但使用:

  1. retrolambda , retrolambda
  2. totallylazy , 完全
  3. gradle-retrolambda , or gradle-retrolambda ,或
  4. Lightweight-Stream-API 轻型-流API

you can. 您可以。 More info see this post and documentation retrolambda, totallylazy, gradle-retrolambda or Lightweight-Stream-API. 更多信息,请参阅这篇文章和文档retrolambda,totallylazy,gradle-retrolambda或Lightweight-Stream-API。 But if you can using Java 8, it's much more easy than using non official API. 但是如果你可以使用Java 8,那么比使用非官方API要容易得多。

Or you can use 或者你可以使用

  1. FunctionalExplained Guava 功能解释番石榴
  2. Functional Java lib 功能Java库

to use functional programming in Java 7, but Stream API more offical and general. 在Java 7中使用函数式编程,但Stream API更加官方和一般。

I don't know such a library, but what is wrong using the plain java, like: 我不知道这样的库,但使用普通的java有什么问题,比如:

List<String> m;
Map<Key,String> map = new HashMap<Key,String>();
int c=1;
for (String i : m) map.put(i,c++);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM