Java:有地图功能吗?


140

我需要一个地图功能。Java中已经有类似的东西了吗?

(对于那些想知道的人:我当然知道如何自己实现这个琐碎的功能...)


1
如果没有,定义自己很简单。但是我想谷歌知道十几种实现?

2
重复的(而更好)在stackoverflow.com/questions/3907412/...
Chowlett

6
@克里斯:这是怎么回事?
艾伯特2010年

1
如果该问题的答案为是,则它还会回答另一个链接的问题。如果答案是否定的(似乎如此),则它们是完全无关的。
艾伯特2010年

1
从Java8开始,这是@delnan可能一直指的是 leveluplunch.com/java/examples/…–
Eternalcode

Answers:


86

从Java 6开始,JDK中没有函数的概念。

番石榴具有功能接口,但是该 方法提供了您所需的功能。
Collections2.transform(Collection<E>, Function<E,E2>)

例:

// example, converts a collection of integers to their
// hexadecimal string representations
final Collection<Integer> input = Arrays.asList(10, 20, 30, 40, 50);
final Collection<String> output =
    Collections2.transform(input, new Function<Integer, String>(){

        @Override
        public String apply(final Integer input){
            return Integer.toHexString(input.intValue());
        }
    });
System.out.println(output);

输出:

[a, 14, 1e, 28, 32]

如今,在Java 8中,实际上已经有了一个map函数,因此我可能会以一种更为简洁的方式编写代码:

Collection<String> hex = input.stream()
                              .map(Integer::toHexString)
                              .collect(Collectors::toList);

8
值得注意的是,虽然使用Guava 可以做到这一点,但您可能不想这样做:code.google.com/p/guava-libraries/wiki/FunctionalExplained(请阅读“注意事项”部分)。
亚当·帕金

2
@AdamParkin是的,但我敢肯定,它是指比这更高级的功能概念,否则他们将不会首先开发transform()方法
Sean Patrick Floyd

2
实际上,不,功能惯用法常常会给性能带来一定的影响,这就是为什么它们会强调您仅在确定满足以下两个条件的情况下才应使用这些功能:整个代码库的LOC净节省,并经过验证懒惰的评估(或至少不是绩效命中)带来的性能提升。并不反对使用它们,只是表明如果要这样做,则应注意实施者的警告。
亚当·帕金

4
@SeanPatrickFloyd现在Java 8已经发布,是否想使用涉及lambda的示例来更新它?喜欢Collections2.transform(input -> Integer.toHexString(intput.intValue())
Daniel Lubarov 2014年

2
@Daniel在Java 8中,我看不到使用Guava这样做的理由。相反,我会去找莱文托夫的答案
肖恩·帕特里克·弗洛伊德

92

从Java 8开始,JDK中提供了一些标准选项:

Collection<E> in = ...
Object[] mapped = in.stream().map(e -> doMap(e)).toArray();
// or
List<E> mapped = in.stream().map(e -> doMap(e)).collect(Collectors.toList());

请参阅java.util.Collection.stream()java.util.stream.Collectors.toList()


140
这太冗长了,这令我内心深处受伤。
Natix 2014年

1
@Natix同意toList()。替换为其他类型:(List<R>)((List) list).replaceAll(o -> doMap((E) o));
leventov

2
可以e -> doMap(e)用替换doMap吗?
jameshfisher 2014年

3
@jameshfisher,是的,类似foo::doMapFoo::doMap
leventov

9
我猜这就是Scala存在的原因。等待Java 12具有可读性。
JulienD

26

有一个很棒的库,叫做Functional Java,可以处理您希望Java拥有但没有的许多东西。再说一遍,还有一种很棒的语言Scala,它可以执行Java应该做的所有事情,但仍然不能与为JVM编写的任何东西兼容。


我对它们如何启用以下语法感兴趣:a.map({int i => i + 42});它们扩展了编译器吗?或添加了预处理器?
安德烈2010年

@Andrey-您可以问他们自己,也可以查看源代码以查看完成情况。这是到源的链接:functionaljava.org/source
Wheaties 2010年

1
@Andrey:示例使用BGGA闭包建议中的语法。尽管有运行中的原型,但它还不在“官方” Java中。
PeterŠtibraný10年

@Andrey:该语法是针对Java闭包的拟议规范的一部分(请参见主页上的倒数第二段)。只有一个典型的实现。
Michael Borgwardt

2
Scala线程劫持:(我希望SO不会像JavaPosse邮件列表那样;)
Jorn,2010年

9

小心Collections2.transform()来自番石榴。该方法的最大优点也是最大的危险:惰性。

查看的文档Lists.transform(),我相信它也适用于Collections2.transform()

该函数延迟应用,在需要时调用。对于返回的列表来说,这是必需的,但是这意味着该函数将多次用于批量操作,如List.contains(java.lang.Object)和List.hashCode()。为使此功能正常运行,功能应该很快。为了避免在返回的列表不需要成为视图时进行延迟评估,请将返回的列表复制到您选择的新列表中。

同样在Collections2.transform()他们提到的文档中,您可以获得实时视图,源列表中的更改会影响转换后的列表。如果开发人员不了解其工作方式,则这种行为可能导致难以跟踪的问题。

如果您想要一个更经典的“地图”,该地图只能运行一次,那么最好使用FluentIterableGuava的,它的操作要简单得多。这是谷歌的例子:

FluentIterable
       .from(database.getClientList())
       .filter(activeInLastMonth())
       .transform(Functions.toStringFunction())
       .limit(10)
       .toList();

transform()这是地图方法。它使用与相同的Function <>“回调” Collections.transform()。您返回的列表是只读的,但copyInto()用于获取读写列表。

否则,当然当java8带有lambda时,这将是过时的。



2

即使这是一个古老的问题,我也想展示另一个解决方案:

只需使用Java泛型和Java 8流定义您自己的操作:

public static <S, T> List<T> map(Collection<S> collection, Function<S, T> mapFunction) {
   return collection.stream().map(mapFunction).collect(Collectors.toList());
}

比您可以编写如下代码:

List<String> hex = map(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.