Stream API の復習
来年の3月18日に Java 8 がリリースされるとあってこのところ日本語での情報もたくさんネット上に出回ってきました。
以前、「JDK8 Lambda その他いろいろ なんでもいいから動かしてみる」シリーズ、「もっと Lambda」シリーズのエントリーで適当に遊んでました。
少し API の変更などあって動かなくなってしまったサンプルもあります。
そこで Java Advent Calendar 2013 のエントリーで復習にぴったりの記事を見つけたので写経させていただくことにしました。
メッセージに「ラムダについて、○ん○出して考えてみた!」とあってビックリしました。
最初「ラムダについて、うんこ出して考えてみた!」と連想してしまい、なんだ!この人はと驚きました。
少ししてから「ラムダについて、ほんき出して考えてみた!」だよなって別解がでました。
まぁ、わざわざ伏せているところをみると作者の罠にまんまとはまったと思う。
ちなみに、○ん○出して考えてみた!というサイトは下記です。
ラムダ禁止について本気出して考えてみた – 9つのパターンで見るStream API
とてもいいですね。
ただ禁止度があるのですがこれはこのサイトの著者が独断で考慮して決められているようです。
プロフェッショナルプログラマの判断なのでおそらくこれに準ずるような企業が多くなるのでしょうかね。
私個人としては、女性と API は新しい方が良い!と言う人間なので
「8. stream中に元のオブジェクトを操作」 以外は使ってもいいんじゃない?
というよりは使いこなせるようになりたい!
Java Advent Calendar 2013 では時期が時期だけに Java 8 に関するエントリーがちらほらとみられます。
どのエントリーも非常に興味深いものばかりです。
それでは自分用のφ(..)メモメモ
おっと、まんま写経しても面白くないので解りやすく変更を加えてコーディングしました。
プログラムの解説はないので興味のあるかたはご自分でお調べくださいませ。
なお、プログラム中に出てくる人物やデータは実際の人物の正確なデータではありませんのであしからず。(なんのこっちゃ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
package jp.yucchi.mystreamexample; import java.time.LocalDate; import java.time.Period; public class MyFriends { public enum Sex { MALE, FEMALE, OKAMA } String name; LocalDate birthday; Sex gender; int Breast; int waist; int hips; public MyFriends(String name, LocalDate birthday, Sex gender, int Breast, int waist, int hips) { this.name = name; this.birthday = birthday; this.gender = gender; this.Breast = Breast; this.waist = waist; this.hips = hips; } public int getAge() { return Period.between(birthday, LocalDate.now()).getYears(); } public String getName() { return name; } public LocalDate getBirthday() { return birthday; } public Sex getGender() { return gender; } public int getBreast() { return Breast; } public int getWaist() { return waist; } public int getHips() { return hips; } void printMyFriends() { System.out.println(name + ", " + this.getAge() + "歳" + ", Gender: " + this.getGender() + ", Breast Size: " + this.getBreast() + ", Waist Size: " + this.getWaist() + ", Hips Size: " + getHips()); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
package jp.yucchi.mystreamexample; import java.time.LocalDate; import java.util.ArrayList; import java.util.Comparator; import java.util.IntSummaryStatistics; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.stream.Collectors; import jp.yucchi.mystreamexample.MyFriends.Sex; public class MyStreamExample { public static void main(String[] args) { List<MyFriends> friend = new ArrayList<>(); friend.add(new MyFriends("柴田 恭平", LocalDate.of(1951, 8, 18), MyFriends.Sex.MALE, 90, 75, 80)); friend.add(new MyFriends("小栗 旬", LocalDate.of(1982, 12, 26), MyFriends.Sex.MALE, 85, 68, 77)); friend.add(new MyFriends("市原 隼人", LocalDate.of(1987, 2, 6), MyFriends.Sex.MALE, 88, 65, 76)); friend.add(new MyFriends("壇 蜜", LocalDate.of(1980, 12, 3), MyFriends.Sex.FEMALE, 85, 60, 89)); friend.add(new MyFriends("北川 景子", LocalDate.of(1986, 8, 22), MyFriends.Sex.FEMALE, 75, 54, 81)); friend.add(new MyFriends("綾瀬 はるか", LocalDate.of(1985, 3, 24), MyFriends.Sex.FEMALE, 88, 61, 91)); friend.add(new MyFriends("佐々木 希", LocalDate.of(1988, 2, 8), MyFriends.Sex.FEMALE, 80, 58, 82)); friend.add(new MyFriends("剛力 彩芽", LocalDate.of(1992, 8, 27), MyFriends.Sex.FEMALE, 77, 58, 84)); friend.add(new MyFriends("堀北 真希", LocalDate.of(1988, 10, 6), MyFriends.Sex.FEMALE, 78, 58, 83)); friend.add(new MyFriends("武井 咲", LocalDate.of(1993, 12, 25), MyFriends.Sex.FEMALE, 76, 58, 82)); friend.add(new MyFriends("深田 恭子", LocalDate.of(1982, 11, 2), MyFriends.Sex.FEMALE, 86, 62, 88)); friend.add(new MyFriends("はるな 愛", LocalDate.of(1976, 7, 21), MyFriends.Sex.OKAMA, 90, 60, 89)); friend.add(new MyFriends("マツコ・デラックス", LocalDate.of(1972, 10, 26), MyFriends.Sex.OKAMA, 150, 150, 150)); // MyFriends 全員表示 System.out.println("<-- MyFriends 全員表示 -->"); friend.stream().forEach((e) -> { e.printMyFriends(); }); // 性別をキーにした Map を作りバストが 85 より大きい友達の人数を入れる。 System.out.println("\n<-- 性別をキーにした Map を作りバストが 85 より大きい友達の人数を入れる -->"); Map<Sex, Long> resultBreastSize = resultBreastSize = groupBySexAndBreast(friend); System.out.println(resultBreastSize); // 性別をキーにした Map を作りバストが 85 より大きい友達の人数を入れる。(別パターン) System.out.println("\n<-- 性別をキーにした Map を作りバストが 85 より大きい友達の人数を入れる。(別パターン) -->"); Map<Sex, Long> resultBreastSize2 = resultBreastSize2 = groupBySexAndBreast2(friend); System.out.println(resultBreastSize2); // 性別が女性のバストの個数(個々では友達の人数)、合計、最小値、平均値、最大値を取得。 System.out.println("\n<-- 性別が女性のバストの個数(ここでは友達の人数)、合計、最小値、平均値、最大値を取得。 -->"); IntSummaryStatistics breastStatistics = breastAverageAndSum(friend); System.out.println("count: " + breastStatistics.getCount() + "\n" + "sum: " + breastStatistics.getSum() + "\n" + "min: " + breastStatistics.getMin() + "\n" + "avarage: " + breastStatistics.getAverage() + "\n" + "max: " + breastStatistics.getMax()); // 女性だけをフィルタリングしてバストのサイズによって降順ソート。 System.out.println("\n<-- 女性だけをフィルタリングしてバストのサイズによって降順ソート。 -->"); List<MyFriends> f = breastSort(friend); f.forEach(e -> { System.out.println(e.getName() + ": Breast: " + e.getBreast()); }); // 女性でバストが 80 より大きい友達だけをフィルタリングしてバストの値に 1000 を足して合計する。 // reduce を使う! sum() のほうが便利だけどね。 System.out.println("\n<-- 女性でバストが 80 より大きい友達だけをフィルタリングしてバストの値に 1000 を足して合計する。 -->"); int breastSum = addBigBreast(friend); System.out.println(breastSum); // 性別によってグルーピングして年齢の若い順に表示させる。 System.out.println("\n<-- 性別によってグルーピングして年齢の若い順に表示させる。 -->"); Map<Sex, List<MyFriends>> resultGender = groupByGender(friend); for (Map.Entry<Sex, List<MyFriends>> keyValue : resultGender.entrySet()) { System.out.println(keyValue.getKey().toString()); for (int i = 0; i < keyValue.getValue().size(); i++) { System.out.println(keyValue.getValue().get(i).getName() + " : " + keyValue.getValue().get(i).getAge()); } } // 女性のバストの大きさでグルーピングして年齢の若い順に表示させる。 System.out.println("\n<-- 女性のバストの大きさでグルーピングして年齢の若い順に表示させる。 -->"); Map<String, List<MyFriends>> resultBreastRank = groupByBreastRank(friend); for (Map.Entry<String, List<MyFriends>> keyValue : resultBreastRank.entrySet()) { System.out.println(keyValue.getKey().toString()); for (int i = 0; i < keyValue.getValue().size(); i++) { System.out.println(keyValue.getValue().get(i).getName() + " : " + keyValue.getValue().get(i).getAge() + " Breast: " + keyValue.getValue().get(i).getBreast()); } } // 性別による平均年齢を計算。 System.out.println("\n<-- 性別による平均年齢を計算。 -->"); Map<Sex, Double> averageAge = groupingBySexAndAve(friend); for (Map.Entry<Sex, Double> keyValue : averageAge.entrySet()) { System.out.println(keyValue.getKey().toString() + " : " + keyValue.getValue().toString()); } // 性別によるグルーピングをして人数の少ない順にソートする。 System.out.println("\n<-- 性別によるグルーピングをして人数の少ない順にソートする。 -->"); List<Sex> sortSex = sortSexCount(friend); sortSex.forEach(System.out::println); // 性別によるグルーピングをして人数の少ない順にソートする。人数も表示させる。 System.out.println("\n<-- 性別によるグルーピングをして人数の少ない順にソートする。人数も表示させる。 -->"); List<Entry<Sex, Long>> sortSex2 = sortSexCount2(friend); sortSex2.forEach(f2 -> { System.out.println(f2.getKey() + " : " + f2.getValue()); }); } private static Map<Sex, Long> groupBySexAndBreast(List<MyFriends> friend) { return friend.stream().collect(Collectors.groupingBy(MyFriends::getGender, Collectors.collectingAndThen(Collectors.toList(), f -> f.stream() .filter(fs -> fs.getBreast() > 85) .count()))); } private static Map<Sex, Long> groupBySexAndBreast2(List<MyFriends> friend) { return friend.stream() .collect(Collectors.groupingBy(MyFriends::getGender)) .entrySet() .stream() .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue() .stream() .filter(f -> f.getBreast() > 85) .count())); } private static IntSummaryStatistics breastAverageAndSum(List<MyFriends> friend) { return friend.stream() .filter(f -> f.getGender() == Sex.FEMALE) .mapToInt(MyFriends::getBreast) .summaryStatistics(); } private static List<MyFriends> breastSort(List<MyFriends> friend) { return friend.stream() .filter(f -> f.getGender() == Sex.FEMALE) .sorted((f1, f2) -> f2.getBreast() - f1.getBreast()) .collect(Collectors.toList()); } private static int addBigBreast(List<MyFriends> friend) { return friend.stream() .filter(f -> f.getGender() == Sex.FEMALE && f.getBreast() > 80) .mapToInt(f -> f.getBreast() + 1000) .reduce(0, (x, y) -> x + y); } private static Map<Sex, List<MyFriends>> groupByGender(List<MyFriends> friend) { return friend.stream() .sorted((f1, f2) -> f1.getAge() - f2.getAge()) .collect(Collectors.groupingBy(f -> f.getGender())); } private static Map<String, List<MyFriends>> groupByBreastRank(List<MyFriends> friend) { return friend.stream() .filter(f -> f.getGender() == Sex.FEMALE) .sorted((f1, f2) -> f1.getAge() - f2.getAge()) .collect(Collectors.groupingBy(f -> { if (f.getBreast() > 85) { return "< 巨乳>"; } if (f.getBreast() > 75) { return "< 乳 >"; } if (f.getBreast() > 65) { return "< 貧乳 >"; } return "・・・"; })); } private static Map<Sex, Double> groupingBySexAndAve(List<MyFriends> friend) { return friend.stream() .collect(Collectors.groupingBy(MyFriends::getGender, Collectors.averagingInt(MyFriends::getAge))); } private static List<Sex> sortSexCount(List<MyFriends> friend) { return friend.stream() .collect(Collectors.groupingBy(MyFriends::getGender, Collectors.counting())) .entrySet() .stream() .sorted(Comparator.comparingLong(Entry::getValue)) .map(Entry::getKey) .collect(Collectors.toList()); } private static List<Entry<Sex, Long>> sortSexCount2(List<MyFriends> friend) { return friend.stream() .collect(Collectors.groupingBy(MyFriends::getGender, Collectors.counting())) .entrySet() .stream() .sorted(Comparator.comparingLong(Entry::getValue)) .collect(Collectors.toList()); } } |
<– MyFriends 全員表示 –>
柴田 恭平, 62歳, Gender: MALE, Breast Size: 90, Waist Size: 75, Hips Size: 80
小栗 旬, 30歳, Gender: MALE, Breast Size: 85, Waist Size: 68, Hips Size: 77
市原 隼人, 26歳, Gender: MALE, Breast Size: 88, Waist Size: 65, Hips Size: 76
壇 蜜, 33歳, Gender: FEMALE, Breast Size: 85, Waist Size: 60, Hips Size: 89
北川 景子, 27歳, Gender: FEMALE, Breast Size: 75, Waist Size: 54, Hips Size: 81
綾瀬 はるか, 28歳, Gender: FEMALE, Breast Size: 88, Waist Size: 61, Hips Size: 91
佐々木 希, 25歳, Gender: FEMALE, Breast Size: 80, Waist Size: 58, Hips Size: 82
剛力 彩芽, 21歳, Gender: FEMALE, Breast Size: 77, Waist Size: 58, Hips Size: 84
堀北 真希, 25歳, Gender: FEMALE, Breast Size: 78, Waist Size: 58, Hips Size: 83
武井 咲, 19歳, Gender: FEMALE, Breast Size: 76, Waist Size: 58, Hips Size: 82
深田 恭子, 31歳, Gender: FEMALE, Breast Size: 86, Waist Size: 62, Hips Size: 88
はるな 愛, 37歳, Gender: OKAMA, Breast Size: 90, Waist Size: 60, Hips Size: 89
マツコ・デラックス, 41歳, Gender: OKAMA, Breast Size: 150, Waist Size: 150, Hips Size: 150
<– 性別をキーにした Map を作りバストが 85 より大きい友達の人数を入れる –>
{FEMALE=2, MALE=2, OKAMA=2}
<– 性別をキーにした Map を作りバストが 85 より大きい友達の人数を入れる。(別パターン) –>
{MALE=2, FEMALE=2, OKAMA=2}
<– 性別が女性のバストの個数(ここでは友達の人数)、合計、最小値、平均値、最大値を取得。 –>
count: 8
sum: 645
min: 75
avarage: 80.625
max: 88
<– 女性だけをフィルタリングしてバストのサイズによって降順ソート。 –>
綾瀬 はるか: Breast: 88
深田 恭子: Breast: 86
壇 蜜: Breast: 85
佐々木 希: Breast: 80
堀北 真希: Breast: 78
剛力 彩芽: Breast: 77
武井 咲: Breast: 76
北川 景子: Breast: 75
<– 女性でバストが 80 より大きい友達だけをフィルタリングしてバストの値に 1000 を足して合計する。 –>
3259
<– 性別によってグルーピングして年齢の若い順に表示させる。 –>
MALE
市原 隼人 : 26
小栗 旬 : 30
柴田 恭平 : 62
FEMALE
武井 咲 : 19
剛力 彩芽 : 21
佐々木 希 : 25
堀北 真希 : 25
北川 景子 : 27
綾瀬 はるか : 28
深田 恭子 : 31
壇 蜜 : 33
OKAMA
はるな 愛 : 37
マツコ・デラックス : 41
<– 女性のバストの大きさでグルーピングして年齢の若い順に表示させる。 –>
< 貧乳 >
北川 景子 : 27 Breast: 75
< 巨乳>
綾瀬 はるか : 28 Breast: 88
深田 恭子 : 31 Breast: 86
< 乳 >
武井 咲 : 19 Breast: 76
剛力 彩芽 : 21 Breast: 77
佐々木 希 : 25 Breast: 80
堀北 真希 : 25 Breast: 78
壇 蜜 : 33 Breast: 85
<– 性別による平均年齢を計算。 –>
FEMALE : 26.125
MALE : 39.333333333333336
OKAMA : 39.0
<– 性別によるグルーピングをして人数の少ない順にソートする。 –>
OKAMA
MALE
FEMALE
<– 性別によるグルーピングをして人数の少ない順にソートする。人数も表示させる。 –>
OKAMA : 2
MALE : 3
FEMALE : 8
TAGS: Java | 2013年12月23日3:28 PM | Comment : 0