我需要一个map功能。 Java中是否有这样的东西?
(对于那些想知道的人:我当然知道如何自己实现这个琐碎的功能......)
答案 0 :(得分:88)
从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()
。
答案 1 :(得分:84)
从Java 6开始,JDK中没有函数的概念。
Guava虽然有Function界面,但是
Collections2.transform(Collection<E>, Function<E,E2>)
method提供了您需要的功能。
示例:强>
// 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);
答案 2 :(得分:25)
有一个名为Functional Java的精彩库,可以处理许多你想要Java拥有的东西,但事实并非如此。再说一次,还有一种非常好的语言Scala,可以完成Java应该完成的所有工作但不会与为JVM编写的任何内容兼容。
答案 3 :(得分:9)
非常小心番石榴的Collections2.transform()
。
这种方法的最大优点也是它最大的危险:它的懒惰。
查看Lists.transform()
的文档,我认为该文档也适用于Collections2.transform()
:
该函数被懒惰地应用,在需要时调用。这是必要的 对于返回的列表是视图,但它表示该函数 将被多次应用于批量操作,如 List.contains(java.lang.Object)和List.hashCode()。为了这个 表现不错,功能要快。避免懒惰评估时 返回的列表不需要是视图,复制返回的列表 进入您选择的新列表。
同样在Collections2.transform()
的文档中,他们提到了实时视图,源列表中的更改会影响转换后的列表。如果开发人员没有意识到它的工作方式,这种行为可能导致难以跟踪的问题。
如果你想要一个更经典的“地图”,它只会运行一次,那么你最好使用FluentIterable
,也来自Guava,它的操作更加简单。这是谷歌的例子:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
这是map方法。它使用相同的函数&lt;&gt; “回调”为Collections.transform()
。您获取的列表是只读的,使用copyInto()
来获取读写列表。
当然,当java8与lambdas一起出现时,这将是过时的。
答案 4 :(得分:2)
这是另一个功能库,您可以使用map:http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
答案 5 :(得分:1)
即使是一个老问题,我也想展示另一个解决方案:
只需使用Java泛型和Java 8流定义您自己的操作:
$reader = new Reader('GeoLite2-City.mmdb');
$record = $reader->city($ip);
// $ip = $_SERVER['REMOTE_ADDR'];
$iso_code = $record->country->isoCode;
$timezone = $record->location->timeZone;
比您可以编写如下代码:
public static <S, T> List<T> mapAll(Collection<S> collection, Function<S, T> mapper) {
return collection.stream().map(mapper).collect(Collectors.toList());
}