Lambdaの遅延処理を確認してみる

櫻庭さん(@)のブログJava in the Box Annex: JavaOne 2013 SF 第4日目を読んでサンプルコードを実装して処理の順序を確認してみました。
JavaSE8のバージョンはb114です。

  • StreamSample.java(★1バイヤーが売り上げた合計を算出)の実行結果

実装からは「Transaction#getBuyer」「Buyer#getState(State=XX)」が最初にデータ件数分(5回)出力されて、その後「Transaction#getPrice(price=999)」が出力されると思っていましたが、遅延処理されているのでデータ件数分(5回)しかloop処理されていないことを確認。
なので終端のオペレーションであるsumを実装しない場合( ★2終端のオペレーションであるsumを除く)は、何もコンソールに出力されませんでした。(当然ですよね)

*** start sum ***
Transaction#getBuyer
Buyer#getState(State=NY)
Transaction#getPrice(price=100)
Transaction#getBuyer
Buyer#getState(State=NY)
Transaction#getPrice(price=200)
Transaction#getBuyer
Buyer#getState(State=NY)
Transaction#getPrice(price=300)
Transaction#getBuyer
Buyer#getState(State=CA)
Transaction#getBuyer
Buyer#getState(State=OH)
*** sum:600 ***

終端のオペレーションかどうかは、JavaDochttp://download.java.net/jdk8/docs/api/index.html?overview-summary.htmlに記載されていました。

public class StreamSample {
    public static void main(String[] args) {
        Transaction[] trans = {new Transaction(100, new Buyer("NY"), new Person("name1"))
                             , new Transaction(200, new Buyer("NY"), new Person("name2"))
                             , new Transaction(300, new Buyer("NY"), new Person("name3"))
                             , new Transaction(111, new Buyer("CA"), new Person("name4"))
                             , new Transaction(222, new Buyer("OH"), new Person("name5"))
        };
        List<Transaction> txns = Arrays.asList(trans);
        // ★1バイヤーが売り上げた合計を算出
        System.out.println("*** start sum ***");
        int sum = txns.stream()
                .filter(t -> t.getBuyer().getState().equals("NY"))
                .mapToInt(t -> t.getPrice())
                .sum();
        System.out.println(String.format("*** sum:%d ***", sum));
        // ★2終端のオペレーションであるsumを除く
        txns.stream()
                .filter(t -> t.getBuyer().getState().equals("NY"))
                .mapToInt(t -> t.getPrice());

        // セラーのみを新しいリストに作成
        List<Person> sellers = txns.stream().map(Transaction::getSeller).collect(Collectors.toList());
        System.out.println(String.format("*** sellers size:%d ***", sellers.size()));
    }   
}
public class Transaction {
    private int price;
    private Buyer buyer;
    private Person seller;
    public Transaction(int price, Buyer buyer, Person seller) {
        this.price = price;
        this.buyer = buyer;
        this.seller = seller;
    }
    public int getPrice() {
        System.out.println(String.format("Transaction#getPrice(price=%d)", price));
        return price;
    }
    public Buyer getBuyer() {
        System.out.println("Transaction#getBuyer");
        return buyer;
    }
    public Person getSeller() {
        System.out.println("Transaction#getSeller");
        return seller;
    }   
}
public class Buyer {
        private String state;
        public Buyer(String state) {
            this.state = state;
        }
        public String getState() {
            System.out.println(String.format("Buyer#getState(State=%s)", state));
            return state;
        }
}
public class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
    public String getName() {
        System.out.println(String.format("Person#getName(Name=%s)", name));
        return name;
    }   
}
  • 最後に

いつもブログを読んで、毎回本当に勉強になります!ほかにもいろいろ実装していつかJavaSE8をお仕事で使えるようになればいいな〜と思っています!