Java:マップ機能はありますか?


140

マップ機能が必要です。このようなJavaの何かはすでにありますか?

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


1
そうでない場合、自分を定義するのは簡単です。しかし、私はグーグルがダースの実装を知っていると思いますか?


6
@クリス:どうして同じ質問なの?
アルバート

1
この質問への回答が「はい」の場合、他のリンクされた質問にも回答します。答えが「いいえ」の場合(そしてそのように思われる場合)、それらは完全に無関係です。
アルバート

1
Java8のように、これは@delnanが言及されているかもしれないものである leveluplunch.com/java/examples/...
Eternalcode

回答:


86

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

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);

8
Guava ではこれを実行できますが、次のようなこと望ましくない場合があることに注意してください:code.google.com/p/guava-libraries/wiki/FunctionalExplained(「警告」セクションをお読みください)。
アダムパーキン2013年

2
@AdamParkinは真実ですが、これはこれよりも高度な機能の概念を指していると確信しています。そうでなければ、そもそもtransform()メソッドを開発しなかったでしょう
Sean Patrick Floyd

2
実際には、いいえ、多くの場合、機能的なイディオムによる明確なパフォーマンスヒットがあります。そのため、概説されている2つの基準、つまりコードベース全体のLOCの正味節約量と実証済みのLOCの純節約が確実である場合にのみ、機能を使用する必要があると強調しています。遅延評価によるパフォーマンスの向上(または少なくともパフォーマンスヒットではない)。それらの使用に反対するのではなく、使用する場合は実装者の警告に注意してください。
アダムパーキン2013年

4
@SeanPatrickFloyd Java 8がリリースされたので、ラムダを含む例でこれを更新しますか?いいねCollections2.transform(input -> Integer.toHexString(intput.intValue())
ダニエル・ルバロフ2014

2
@Daniel Java 8では、Guavaでそれを行う理由がわかりません。代わりに私はleventovの答えを求めます
Sean Patrick Floyd

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 2014年

2
e -> doMap(e)ちょうどで置き換えることができますdoMapか?
jameshfisher 2014

3
@jameshfisher、はい、foo::doMapまたはのようなものFoo::doMap
leventov 2014

9
これがScalaが存在する理由だと思います。Java 12が読みやすいものになるまで待ちます。
JulienD

26

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


彼らは次の構文をどのように有効にしたのか興味があります:a.map({int i => i + 42});コンパイラを拡張しましたか?または追加されたプリプロセッサ?
Andrey

@Andrey-あなたは彼らに自分自身に尋ねるか、ソースコードをチェックしてどのように行われるかを確認できます。ソースへのリンクは次のとおりです
。functionaljava.org/

1
@Andrey:例では、BGGAクロージャー提案の構文を使用しています。実行中のプロトタイプはありますが、まだ「公式」のJavaには含まれていません。
PeterŠtibraný2010年

@Andrey:その構文は、Javaでのクロージャーの仕様の提案の一部です(ホームページの最後から2番目の段落を参照)。典型的な実装しかありません。
Michael Borgwardt、

2
Scalaスレッドハイジャック:(SOがJavaPosseメーリングリストのようにならないことを願っています;)
Jorn

9

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

ドキュメントを見てLists.transform()、私はにも適用されると信じて、Collections2.transform()

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

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

より古典的な「マップ」が必要な場合、それは1度だけ実行されます。さらにFluentIterable、操作がはるかに簡単なGuavaのを使用したほうがよいでしょう。ここにそれのためのグーグルの例があります:

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

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

それ以外の場合はもちろん、java8にラムダが付属している場合、これは廃止されます。



2

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

Java Genericsと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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.