2016-12-17 4 views
1

PersonクラスにFirstName、LastName、Age、Salaryなどのフィールドがあるとしましょう。ここでPersonがListであるC#linqでこのコードを実行しました。Java 8でC#のように匿名オブジェクトを取得するlinq

var lstFirstAndLastNamesOnly = persons.Where(x => x.Age > 35).Select(x => new {x.FirstName, x.LastName}).ToList(); 

これは、FirstNameとLastNameを持つ匿名のタイプを取得します。 Java 8でこれをどうやって書くのですか?私がクラスに100のフィールドを言うと、ほんの一握りのフィールドだけが返されるので、より良い方法ができます。

+4

C#と同じように、Javaでは匿名型は存在しません。 (はい、あなたは匿名のクラスを持つことができますが、意味のある方法で実際に同じではなく、Java 8ストリームで使用するのは非常に醜いでしょう)。 –

+0

Javaは厳密に静的に型指定されていますが、アノニマス型 "と呼ばれる。 – dabadaba

+2

@dabadaba C#の匿名型は動的ではありません。静的型付けされたエコシステムの一部です。 (それらのセマンティクスはコンパイル時に適用されます) –

答えて

3

Javaプログラミング言語には匿名型がありますが、そのC#の例ほど有用ではありません。すなわち、次のように動作します:あなたが気づかれるように

persons.stream().filter(x -> x.age > 35) 
    .map(x -> new Object(){ String first=x.firstName, last=x.lastName; }) 
    .forEach(name -> System.out.println(name.first+" "+name.last)); 

は、匿名型の宣言は、まだ匿名型のスーパータイプになりますタイプの指定が必要です。さらに、データを保持するメンバーを型と名前で正式に宣言する必要があります。

ラムダ式は、型を指定せずに変数(パラメータ)を宣言し、コンパイラに推論させる唯一の場所です。

匿名型の関連プロパティは名前を持たないため、明示的な型が必要な場合は、その型の変数を宣言することはできません。 Javaプログラミング言語には、var name宣言構文がありません。

あなたは

System.out.println(
    persons.stream().filter(x -> x.age > 35) 
     .map(x -> new Object(){ String a=x.firstName, b=x.lastName; }) 
     .findFirst().get().a 
); 

のように、変数せずに、流暢な文脈でそれにアクセスすることができますが、これは唯一の単一のメンバーにアクセスすることができますので、あなただけの単一のメンバーが必要な場合は、として、それは、ほとんど使用さです、あなたは最初にメンバーの値にmapすることができます。あなたが不均一要素を入力した場合は特に、当然のことながら、彼らは本当のタプルのための代替ではない、

List<String[]> lstFirstAndLastNamesOnly = persons.stream() 
    .filter(x -> x.age > 35) 
    .map(x -> new String[] { x.firstName, x.lastName }) 
    .collect(Collectors.toList()); 
lstFirstAndLastNamesOnly 
    .forEach(name -> System.out.println(name[0]+" "+name[1])); 

しかし:

この具体例では、あなたの代わりに2つの要素Stringのアレイを使用することができます。

+0

'forEach()'で印刷やその他の目的で匿名型をすぐに使用している場合に機能します。さもなければ、Objectが返され、Javaはタイプを自動的に推論する 'var'型の機能を持たないので、' Stream 'としなければなりません。今はメンバーにアクセスできなくなりました。 – Jagannath

+0

@ジャガナス:これはまさにこの答えが言うことです。 – Holger

関連する問題