2017-01-14 10 views
1

私はPOJOPerson.java内のファイルがあります:java8 Streamのfilter()メソッドとmap()メソッドは反復を使用しますか?

public class Person { 
    private String name; 
    private int age; 

    public Person(String n, int a) { 
     name = n; 
     age = a; 
    } 

    public String getName() { 
     return name; 
    } 

    public int getAge() { 
     return age; 
    } 

    public boolean isAdult() { 
     return getAge() >= 18;  
    } 
} 

をそして私は人々のリストを作成し、使用して、リストからフィルタリングした印刷コンテンツにストリーミングDemo.javaファイルがあります:

import java.util.*; 

public class Demo { 
    public static void main(String[] args) { 
     List<Person> people = createPeople(); 
     List<String> names = people.stream() 
            .filter(person -> person.isAdult()) 
            .map(person -> person.getName()) 
            .collect(toList()); 
     System.out.println(names); 
    } 

    private static List<Person> createPeople() { 
     List<Person> people = new ArrayList<>(); 
     people.add("John", 19); 
     people.add("Joe", 21); 
     people.add("Jill", 16); 
     people.add("Sylvester", 18); 
     people.add("Hillary", 17); 
     people.add("Donald", 4); 

     return people; 
    } 
} 

を私は知りたかった:

1>filter()map()は内部でループを使用してPerson ob Listpeopleのjects?

2>はいの場合、リスト内のすべてのオブジェクトを2回繰り返します(1回目の繰り返しはfilter()、その他はmap())。

3>もう一度「map()」または「filter()」というメソッドを追加すると、3回目に再びすべてのオブジェクトがループされますか?

4>もう一度答えると、伝統的な命令的スタイルのコーディングとはどのようにパフォーマンスが違うのですか(実際は伝統的な命令的なスタイルでは、たいていの場合1つのシングルループですべてのフィルタリングとマッピングができます。したがって、パフォーマンスは賢明です。このような場合、命令型のコーディングはストリームよりも優れています。)

PS:上記の質問にNoがある場合は、どのように動作するかについての説明を追加してください。

もう1つ:内部でストリームの反復処理と命令型の反復処理がありますか?詳細な説明をして、私の知識にもっと光を当ててください。

+1

1>はい、それを反復処理するストリームではなく、リストの上に。 2> no 3> - > 4 - –

+0

2>いいえ?それでどうやって動くの? @FrankPuffer –

+0

@FrankPufferリストの反復処理とストリームの反復処理はどのように異なっていますか? –

答えて

6

map()ListではなくStreamを返しているため、最初にコードがコンパイルされません。ターミナル操作でストリームチェーンを終了する必要があります。filter()map()は両方ともintermediate operationsです。 javadocの中にそうそう言います。あなたの場合は、コンパイルしてokを実行するには.collect(Collectors.toList())を追加する必要があります。

1>filter()map()は内部List人々のすべてのPersonのオブジェクトを反復処理するためにループを使用していますか?

いいえ端末操作でループが行われています。

質問2〜4は答えがYesと仮定されているため、答えはありません。

上記の質問のいずれかにNoがある場合は、どのように動作するかに関する説明を追加してください。

documentationを読むか、ウェブを検索してください。それはかなりよく説明されています。

内部でストリームの反復処理が行われているのか、命令型の反復処理がありますか?

はい。ストリームは並列スレッドの実行を利用できます。たとえシングルスレッドであっても、全体的な操作の仕方に違いがありますが、論理的には高いレベルでは基本的に同じです。


あなたのコードでは、collect()コールが追加されて、同等の不可欠のコードは次のようになります。

List<String> names = new ArrayList<>(); 
for (Person person : people) 
    if (person.isAdult()) 
     names.add(person.getName()); 

最初のユーザーが定義した、ストリーム・ロジックが何をするかと比較しますラムダはfilter()map()

Predicate<Person>  filter = person -> person.isAdult(); 
Function<Person, String> map = person -> person.getName(); 
0123に渡されました

次にあなたがCollectors.toList()を呼び出すことによってCollectorを取得し、それが提供するオブジェクトを取得します

Collector<String, List<String>, List<String>> collector = (Collector) Collectors.toList(); 
Supplier<List<String>>    supplier = collector.supplier(); 
BiConsumer<List<String>, String>  accumulator = collector.accumulator(); 
Function<List<String>, List<String>> finisher = collector.finisher(); 

stream()呼び出しは基本的にIteratorを提供し(それが実際にSpliteratorだ)とcollectコールが繰り返されますので、組み合わせループはforと同じです。 StreamSpliteratorcollect()の仕組みの完全な論理については触れません。 Web上で詳細を知りたい場合は、Webを検索してください。

ので、上記不可欠forループは次のようになります。

List<String> list = supplier.get();  // list = new ArrayList<>() 
for (Person person : people)    // collect() loop using Spliterator from stream() 
    if (filter.test(person)) {    // if (person.isAdult()) 
     String value = map.apply(person); // value = person.getName() 
     accumulator.accept(list, value); // list.add(value) 
    } 
List<String> names = finisher.apply(list); // names = list 
+0

かなりよく説明されています。どうもありがとう。私は 'collect()'呼び出しを追加して、さらなる読者に混乱を与えないようにしました。 –

関連する問題