64

Java ではメソッドをパラメーターとして渡すことができないため、Python のようなリスト内包表記を Java で実装するには、どのようなトリックを使用しますか?

文字列のリスト (ArrayList) があります。別のリストを取得するには、関数を使用して各要素を変換する必要があります。String を入力として受け取り、別の String を出力として返す関数がいくつかあります。リストと関数をパラメーターとして指定できる汎用メソッドを作成して、各要素が処理されたリストを取得できるようにするにはどうすればよいですか。文字通りの意味では不可能ですが、どのようなトリックを使用すればよいですか?

もう 1 つのオプションは、小さな文字列処理関数ごとに新しい関数を作成することです。この関数は、単純にリスト全体をループしますが、これはあまりクールではありません。

4

7 に答える 7

38

基本的に、Function インターフェイスを作成します。

public interface Func<In, Out> {
    public Out apply(In in);
}

次に、匿名サブクラスをメソッドに渡します。

メソッドは、関数を各要素にインプレースで適用できます。

public static <T> void applyToListInPlace(List<T> list, Func<T, T> f) {
    ListIterator<T> itr = list.listIterator();
    while (itr.hasNext()) {
        T output = f.apply(itr.next());
        itr.set(output);
    }
}
// ...
List<String> myList = ...;
applyToListInPlace(myList, new Func<String, String>() {
    public String apply(String in) {
        return in.toLowerCase();
    }
});

または、新しいものを作成しますList(基本的に、入力リストから出力リストへのマッピングを作成します):

public static <In, Out> List<Out> map(List<In> in, Func<In, Out> f) {
    List<Out> out = new ArrayList<Out>(in.size());
    for (In inObj : in) {
        out.add(f.apply(inObj));
    }
    return out;
}
// ...
List<String> myList = ...;
List<String> lowerCased = map(myList, new Func<String, String>() {
    public String apply(String in) {
        return in.toLowerCase();
    }
});

どちらが好ましいかは、ユースケースによって異なります。リストが非常に大きい場合は、インプレース ソリューションが唯一の実行可能なソリューションである可能性があります。多くの異なる関数を同じ元のリストに適用して多くの派生リストを作成したい場合は、mapバージョンが必要になります。

于 2009-05-22T18:03:05.003 に答える
16

Google Collections ライブラリには、単純な Java がサポートするよりもはるかに高いレベルで、機能的な方法 (フィルター、マップ、フォールドなど) でコレクションとイテレーターを操作するためのクラスが多数あります。Function と Predicate のインターフェイスと、それらを使用してコレクションを処理するメソッドが定義されているため、その必要はありません。また、Java ジェネリックの扱いを簡単にする便利な関数もあります。

また、コレクションのフィルタリングにHamcrest **も使用しています。

2 つのライブラリは、アダプター クラスと簡単に組み合わせることができます。


** 関心の宣言: 私は Hamcrest の共同執筆者です

于 2009-05-22T18:02:12.570 に答える
4

Apache Commons CollectionsUtil.transform(Collection, Transformer) も別のオプションです。

于 2009-05-22T18:54:46.150 に答える
1

私はJavaでリスト内包表記を書くためにこのプロジェクトを構築しています.今はhttps://github.com/farolfo/list-comprehension-in-java

// { x | x E {1,2,3,4} ^ x is even }
// gives {2,4}

Predicate<Integer> even = x -> x % 2 == 0;

List<Integer> evens = new ListComprehension<Integer>()
    .suchThat(x -> {
        x.belongsTo(Arrays.asList(1, 2, 3, 4));
        x.is(even);
    });
// evens = {2,4};

そして、出力式を次のような方法で変換したい場合

// { x * 2 | x E {1,2,3,4} ^ x is even }
// gives {4,8}

List<Integer> duplicated = new ListComprehension<Integer>()
    .giveMeAll((Integer x) -> x * 2)
    .suchThat(x -> {
        x.belongsTo(Arrays.asList(1, 2, 3, 4));
        x.is(even);
    });
// duplicated = {4,8}
于 2015-06-18T18:58:19.817 に答える