web-dev-qa-db-ja.com

Java:マップ関数はありますか?

map 関数が必要です。 Javaにはすでにこのようなものがありますか?

(疑問に思う人のために:私はもちろんこの些細な機能を自分で実装する方法を知っています...)

133
Albert

Java 6以降、JDKには関数の概念がありません。

Guava には Function インターフェイスがありますが、
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で実際にマップ関数があるので、おそらくもっと簡潔な方法でコードを書くでしょう。

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

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() を参照してください。

89
leventov

Functional Java と呼ばれるすばらしいライブラリがあります。これは、Javaに必要なものの多くを処理しますが、そうではありません。また、この素晴らしい言語Scalaもあります。これはJavaが行うべきすべてのことを行いますが、JVM用に作成されたものとの互換性はありません。

26
wheaties

グアバのCollections2.transform()には非常に注意してください。この方法の最大の利点は、その最大の危険性である怠:です。

Lists.transform()のドキュメントを見てください。これはCollections2.transform()にも当てはまると思います:

この関数は遅延的に適用され、必要なときに呼び出されます。これは返されるリストをビューにするために必要ですが、関数はList.contains(Java.lang.Object)やList.hashCode()などの一括操作に何度も適用されることを意味します。これがうまく機能するためには、機能が高速でなければなりません。返されたリストがビューである必要がない場合に遅延評価を回避するには、返されたリストを選択した新しいリストにコピーします。

また、Collections2.transform()のドキュメントでは、ライブビューを取得することが記載されており、ソースリストの変更は変換されたリストに影響します。開発者がその動作方法を認識していない場合、この種の動作は追跡が困難な問題につながる可能性があります。

一度だけ実行される、より古典的な「マップ」が必要な場合は、 FluentIterable を使用することをお勧めします。これもGuavaの操作で、はるかに簡単です。 Googleの例は次のとおりです。

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

transform()はmapメソッドです。 Collections.transform()と同じFunction <>「コールバック」を使用します。返されるリストは読み取り専用ですが、copyInto()を使用して読み取り/書き込みリストを取得します。

それ以外の場合、もちろんJava8がラムダを使用するようになると、これは廃止されます。

9

これは、マップを使用できる別の機能ライブラリです。 http://code.google.com/p/totallylazy/

sequence(1, 2).map(toString); // lazily returns "1", "2"
2

それは古い質問ですが、別の解決策を示したいと思います:

JavaジェネリックとJava 8ストリームを使用して独自の操作を定義するだけです。

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

このようなコードを書くことができるより:

List<String> hex = mapAll(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);
1
IPP Geek