package jp.yucchi.jdk9eaexample;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
*
* @author Yucchi
*/
public class JDK9eaExample {
public static void main(String[] args) {
List<MyFriends> myFriends = new ArrayList<>();
myFriends.add(new MyFriends(1, "柴田 恭平", LocalDate.of(1951, 8, 18), MyFriends.Sex.MALE, "81300000001", "俳優", "静岡県", 80,
List.of("野球", "サッカー", "三味線")));
myFriends.add(new MyFriends(2, "小栗 旬", LocalDate.of(1982, 12, 26), MyFriends.Sex.MALE, "81300000002", "俳優", "東京都", 75,
List.of("野球", "音楽鑑賞", "フィギア収集", "マンガ")));
myFriends.add(new MyFriends(3, "市原 隼人", LocalDate.of(1987, 2, 6), MyFriends.Sex.MALE, "81300000003", "俳優", "神奈川県", 70,
List.of("テレビゲーム", "カラオケ")));
myFriends.add(new MyFriends(4, "安倍 晋三", LocalDate.of(1954, 9, 21), MyFriends.Sex.MALE, "81300000004", "政治家", "東京都", 40,
List.of("ゴルフ", "映画観賞", "読書", "水泳")));
myFriends.add(new MyFriends(5, "ドナルド トランプ", LocalDate.of(1946, 1, 20), MyFriends.Sex.MALE, "1100000005", "政治家", "ニューヨーク", 55,
List.of("ゴルフ", "プロレス観戦")));
myFriends.add(new MyFriends(6, "桐谷 美玲", LocalDate.of(1989, 12, 16), MyFriends.Sex.FEMALE, "81300000006", "女優", "千葉県", 95,
List.of("音楽鑑賞", "サッカー観戦")));
myFriends.add(new MyFriends(7, "有村 架純", LocalDate.of(1993, 2, 13), MyFriends.Sex.FEMALE, "81300000007", "女優", "兵庫県", 90,
List.of("お菓子づくり", "散歩", "買い物")));
myFriends.add(new MyFriends(8, "綾瀬 はるか", LocalDate.of(1985, 3, 24), MyFriends.Sex.FEMALE, "81300000008", "女優", "広島県", 85,
List.of("カラオケ", "お菓子づくり", "足首回し")));
myFriends.add(new MyFriends(9, "佐々木 希", LocalDate.of(1988, 2, 8), MyFriends.Sex.FEMALE, "81300000009", "女優", "秋田県", 81,
List.of("アクセサリー収集")));
myFriends.add(new MyFriends(10, "剛力 彩芽", LocalDate.of(1992, 8, 27), MyFriends.Sex.FEMALE, "81300000010", "女優", "神奈川県", 76,
List.of("お菓子づくり", "フルート", "料理")));
myFriends.add(new MyFriends(11, "堀北 真希", LocalDate.of(1988, 10, 6), MyFriends.Sex.FEMALE, "81300000011", "女優", "東京都", 88,
List.of("読書", "サイクリング")));
myFriends.add(new MyFriends(12, "深田 恭子", LocalDate.of(1982, 11, 2), MyFriends.Sex.FEMALE, "81300000012", "女優", "東京都", 80,
List.of("サーフィン", "書道", "ピアノ", "水泳")));
myFriends.add(new MyFriends(13, "小池 百合子", LocalDate.of(1952, 7, 15), MyFriends.Sex.FEMALE, "81300000013", "政治家", "兵庫県", 50,
List.of("ゴルフ", "テニス")));
myFriends.add(new MyFriends(14, "宇多田 ヒカル", LocalDate.of(1983, 1, 19), MyFriends.Sex.FEMALE, "81300000014", "歌手", "ニューヨーク", 91,
List.of("読書", "マンガ", "絵画")));
myFriends.add(new MyFriends(15, "西野 カナ", LocalDate.of(1989, 3, 18), MyFriends.Sex.FEMALE, "81300000015", "歌手", "三重県", 77,
List.of("料理", "海外旅行")));
myFriends.add(new MyFriends(16, "きゃりーぱみゅぱみゅ", LocalDate.of(1993, 1, 29), MyFriends.Sex.FEMALE, "81300000016", "歌手", "東京都", 74,
List.of("釣り", "音楽")));
myFriends.add(new MyFriends(17, "はるな 愛", LocalDate.of(1972, 7, 21), MyFriends.Sex.OKAMA, "81300000017", "おネエ系タレント", "大阪府", 69,
List.of("釣り", "サーフィン", "スノーボード", "ゴルフ", "映画鑑賞")));
myFriends.add(new MyFriends(18, "マツコ・デラックス", LocalDate.of(1972, 10, 26), MyFriends.Sex.OKAMA, "81300000018", "おネエ系タレント", "千葉県", 88,
List.of("女装", "ドライブ")));
// MyFriends 全員表示
System.out.println("<-- MyFriends -->");
myFriends.stream().forEach(MyFriends::printMyFriends);
// Optional::stream
Function<MyFriends, Optional<MyFriends>> optionalStreamMapper = mf -> mf.getFavorabilityRating() >= 80 ? Optional.of(mf) : Optional.empty();
System.out.println("\nJava8 Optional::stream");
myFriends.stream()
.map(optionalStreamMapper)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList())
.forEach(MyFriends::printMyFriends);
System.out.println("\nJava9 Optional::stream");
myFriends.stream()
.map(optionalStreamMapper)
.flatMap(Optional::stream)
.collect(Collectors.toList())
.forEach(MyFriends::printMyFriends);
// Stream ofNullable
Function<MyFriends, MyFriends> streamOfNullableMapper = mf -> mf.getAge() < 25 ? mf : null;
System.out.println("\nJava8 Stream ofNullable");
myFriends.stream()
.map(streamOfNullableMapper)
.flatMap(s -> s != null ? Stream.of(s) : Stream.empty())
.collect(Collectors.toList())
.forEach(MyFriends::printMyFriends);
System.out.println("\nJava9 Stream ofNullable");
myFriends.stream()
.map(streamOfNullableMapper)
.flatMap(mf -> Stream.ofNullable(mf))
.collect(Collectors.toList())
.forEach(MyFriends::printMyFriends);
System.out.println("\nID で友達を検索");
// ID で友達を検索
findById(7, myFriends);
// 無効な ID で友達を検索
findById(27, myFriends);
System.out.println("\n名前で友達を検索");
// 名前で友達を検索
findByName("桐谷 美玲", myFriends);
// 無効な名前で友達を検索
findByName("二階堂 ふみ", myFriends);
System.out.println("\n電話番号で友達を検索");
// 電話番号で友達を検索
findByPhoneNumber("1100000005", myFriends);
// 無効な電話番号で友達を検索
findByPhoneNumber("81300003015", myFriends);
System.out.println("\nID、名前、電話番号の順に友達を検索");
// ID、名前、電話番号の順に友達を検索
// ID、名前、電話番号 すべて有効 <14: 宇多田 ヒカル, 34歳, Gender: FEMALE, 電話番号: 81300000014, 職業: 歌手, 出身地: ニューヨーク, 好感度: 911, 趣味: [読書, マンガ, 絵画]>
findByMyFriendsIdOrNameOrPhoneNumber(14, "西野 カナ", "81300000016", myFriends);
// 名前、電話番号 有効 <15: 西野 カナ, 27歳, Gender: FEMALE, 電話番号: 81300000015, 職業: 歌手, 出身地: 三重県, 好感度: 77, 趣味: [料理, 海外旅行]>
findByMyFriendsIdOrNameOrPhoneNumber(99, "西野 カナ", "81300000016", myFriends);
// 電話番号 有効 <16: きゃりーぱみゅぱみゅ, 24歳, Gender: FEMALE, 電話番号: 81300000016, 職業: 歌手, 出身地: 東京都, 好感度: 74, 趣味: [釣り, 音楽]>
findByMyFriendsIdOrNameOrPhoneNumber(99, "二階堂 ふみ", "81300000016", myFriends);
// ID、名前、電話番号 すべて無効
findByMyFriendsIdOrNameOrPhoneNumber(99, "二階堂 ふみ", "81300009014", myFriends);
System.out.println("\n職業別にグループ化し好感度 90 以上の友達を検索");
findByProfession(myFriends, 90);
System.out.println("\n出身地別にグループ化して友達の名前を検索");
findByBirthplace(myFriends);
System.out.println("\n職業別にグループ化し趣味を検索");
findByHobbyByProfession(myFriends);
System.out.println("\n年齢が若い順に友達を表示");
findByYoungOrder(myFriends);
System.out.println("\n年齢が若い順に好感度が70未満の友達がヒットするまで検索");
findByYoungFriendsByFavorabilityRating(myFriends, 70);
System.out.println("\n年齢が大きい順に好感度が90未満の友達がヒットするまでスキップして検索");
findByOldFriendsByFavorabilityRating(myFriends, 90);
System.out.println("\n条件付きで年齢が若い順に友達を表示 27歳以下スキップ、34歳まで リミット");
findByConditionalYoungOrder(myFriends, 27, 34);
System.out.println("\nID 1 から Double Calculation で計算して友達を検索 ただし、ID は 50 未満の範囲とする。(実質 32 まで)");
findByIdDoubleCalculation(myFriends, 50);
}
// ID で友達を検索して表示する
private static void findById(int id, List<MyFriends> myFriends) {
Optional<MyFriends> myFriendsById = findMyFriendsById(id, myFriends);
// // Java8 * myFriendsById.ifPresent(MyFriends::printMyFriends); だと存在しなかったときの処理ができなくて不便 (>_<)
// if (myFriendsById.isPresent()) { // ここで既に負けている(>_<)
// myFriendsById.get().printMyFriends();
// } else {
// notFoundById(id);
// }
myFriendsById.ifPresentOrElse(MyFriends::printMyFriends, () -> notFoundById(id));
}
// ID で友達を検索 Optional<MyFriends> オブジェクト取得
private static Optional<MyFriends> findMyFriendsById(int id, List<MyFriends> myFriends) {
return myFriends
.stream()
.filter(e -> e.getId() == id)
.findFirst();
}
// ID で友達を検索して存在しなかった場合のメッセージを表示
private static void notFoundById(int id) {
System.out.println("ID " + id + " の友達は存在しません。");
}
// 名前で友達を検索して表示する
private static void findByName(String name, List<MyFriends> myFriends) {
Optional<MyFriends> myFriendsByName = findMyFriendsByName(name, myFriends);
myFriendsByName.ifPresentOrElse(MyFriends::printMyFriends, () -> notFoundByName(name));
}
// 名前で友達を検索 Optional<MyFriends> オブジェクト取得
private static Optional<MyFriends> findMyFriendsByName(String name, List<MyFriends> myFriends) {
return myFriends
.stream()
.filter(e -> Objects.equals(e.getName(), name))
.findFirst();
}
// 名前で友達を検索して存在しなかった場合のメッセージを表示
private static void notFoundByName(String name) {
System.out.println("名前 " + name + " の友達は存在しません。");
}
// 電話番号で友達を検索して表示する
private static void findByPhoneNumber(String phoneNumber, List<MyFriends> myFriends) {
Optional<MyFriends> myFriendsByPhoneNumber = findMyFriendsByPhoneNumber(phoneNumber, myFriends);
myFriendsByPhoneNumber.ifPresentOrElse(MyFriends::printMyFriends, () -> notFoundByPhoneNumber(phoneNumber));
}
// 電話番号で友達を検索 Optional<MyFriends> オブジェクト取得
private static Optional<MyFriends> findMyFriendsByPhoneNumber(String phoneNumber, List<MyFriends> myFriends) {
return myFriends
.stream()
.filter(e -> Objects.equals(e.getPhoneNumber(), phoneNumber))
.findFirst();
}
// 電話番号で友達を検索して存在しなかった場合のメッセージを表示
private static void notFoundByPhoneNumber(String phoneNumber) {
System.out.println("電話番号 " + phoneNumber + " の友達は存在しません。");
}
// ID、名前、電話番号の順に友達を検索して表示する
private static void findByMyFriendsIdOrNameOrPhoneNumber(int id, String name, String phoneNumber, List<MyFriends> myFriends) {
Optional<MyFriends> myFriendsById = findMyFriendsById(id, myFriends);
Optional<MyFriends> myFriendsByName = findMyFriendsByName(name, myFriends);
Optional<MyFriends> myFriendsByPhoneNumber = findMyFriendsByPhoneNumber(phoneNumber, myFriends);
myFriendsById
.or(() -> myFriendsByName
.or(() -> myFriendsByPhoneNumber))
.ifPresentOrElse(MyFriends::printMyFriends, () -> notFoundByIdOrNameOrPhoneNumber(id, name, phoneNumber));
}
// ID、名前、電話番号の順に友達を検索して存在しなかった場合のメッセージを表示
private static void notFoundByIdOrNameOrPhoneNumber(int id, String name, String phoneNumber) {
System.out.println("ID " + id + "、名前 " + name + "、電話番号 " + phoneNumber + "の何れかに合致する友達は存在しません。");
}
// 職業別にグループ化し好感度 90 以上の友達を検索
private static void findByProfession(List<MyFriends> myFriends, int favorabilityRating) {
// Java9
Map<String, List<MyFriends>> myFriendsByProfession
= myFriends.stream().collect(
Collectors.groupingBy(MyFriends::getProfession,
Collectors.filtering(e -> e.getFavorabilityRating() >= favorabilityRating,
Collectors.toList())));
// // Java8 No Good!!
// Map<String, List<MyFriends>> myFriendsByProfession
// = myFriends.stream()
// .filter(e -> e.getFavorabilityRating() >= favorabilityRating)
// .collect(
// Collectors.groupingBy(MyFriends::getProfession,
// CollectorstoList()));
// // Java8
// Map<String, List<MyFriends>> myFriendsByProfession
// = myFriends.stream().collect(
// Collectors.groupingBy(MyFriends::getProfession,
// Collectors.collectingAndThen(Collectors.toList(),
// e -> e.stream()
// .filter(v -> v.getFavorabilityRating() >= favorabilityRating)
// .collect(Collectors.toList()))));
myFriendsByProfession.entrySet().forEach(es -> {
if (es.getValue().isEmpty()) {
System.out.println("Key= " + es.getKey() + ", 好感度 " + favorabilityRating + "以上の友達は存在しません。");
}
es.getValue().forEach(v -> {
System.out.println("Key= " + es.getKey() + ", Value = " + getMyFriendsInfo(v));
});
});
}
private static String getMyFriendsInfo(MyFriends v) {
return v.getId() + ": " + v.getName() + ", " + v.getAge() + "歳" + ", Gender: "
+ v.getGender() + ", 電話番号: " + v.getPhoneNumber()
+ ", 職業: " + v.getProfession() + ", 出身地: " + v.getBirthplace()
+ ", 好感度: " + v.getFavorabilityRating() + ", 趣味: " + v.getHobby();
}
// 出身地別にグループ化して友達の名前を検索 Java8 で問題なしのケース
private static void findByBirthplace(List<MyFriends> myFriends) {
Map<String, Set<String>> myFriendsByBirthplace
= myFriends.stream()
.collect(
Collectors.groupingBy(MyFriends::getBirthplace,
Collectors.mapping(MyFriends::getName, Collectors.toSet())));
myFriendsByBirthplace.entrySet().forEach(es -> {
if (es.getValue().isEmpty()) {
System.out.println("Key= " + es.getKey() + " の友達は存在しません。");
}
System.out.println("Key= " + es.getKey() + ", Value = " + es.getValue());
});
}
// 職業別にグループ化し趣味を検索 Java9 でスマートになる
private static void findByHobbyByProfession(List<MyFriends> myFriends) {
Map<String, Set<String>> myFriendsByHobbyByProfession
= myFriends.stream()
.collect(
Collectors.groupingBy(MyFriends::getProfession,
// Collectors.mapping(MyFriends::getHobby, Collectors.toSet()))); // Map<String, Set<List<String>>> Java8
Collectors.flatMapping(e -> e.getHobby().stream(), Collectors.toSet())));
myFriendsByHobbyByProfession.entrySet().forEach(es -> {
if (es.getValue().isEmpty()) {
System.out.println("Key= " + es.getKey() + " の趣味はありません。");
}
System.out.println("Key= " + es.getKey() + ", Value = " + es.getValue());
});
}
// 年齢が若い順に友達を表示
private static void findByYoungOrder(List<MyFriends> myFriends) {
myFriends.stream()
.sorted(Comparator.comparing(MyFriends::getAge))
.forEach(MyFriends::printMyFriends);
}
// 年齢が若い順に好感度が70未満の友達がヒットするまで検索
private static void findByYoungFriendsByFavorabilityRating(List<MyFriends> myFriends, int favorabilityRating) {
myFriends.stream()
.sorted(Comparator.comparing(MyFriends::getAge))
.takeWhile(e -> e.getFavorabilityRating() >= favorabilityRating)
.forEach(MyFriends::printMyFriends);
}
// 年齢が大きい順に好感度が90未満の友達がヒットするまでスキップして検索
private static void findByOldFriendsByFavorabilityRating(List<MyFriends> myFriends, int favorabilityRating) {
myFriends.stream()
.sorted(Comparator.comparing(MyFriends::getAge).reversed())
.dropWhile(e -> e.getFavorabilityRating() < favorabilityRating)
.forEach(MyFriends::printMyFriends);
}
// 条件付きで年齢が若い順に友達を表示 27歳以下スキップ、34歳まで リミット
private static void findByConditionalYoungOrder(List<MyFriends> myFriends, int skip, int limit) {
myFriends.stream()
.sorted(Comparator.comparing(MyFriends::getAge))
.dropWhile(e -> e.getAge() <= skip)
.takeWhile(e -> e.getAge() <= limit)
.forEach(MyFriends::printMyFriends);
}
// ID 1 から Double Calculation で計算して友達を検索 ただし、ID は 50 未満の範囲とする。(実質 32 まで)
private static void findByIdDoubleCalculation(List<MyFriends> myFriends, int id) {
IntStream.iterate(1, i -> i <= id, i -> i *= 2).forEach(i -> {
findById(i, myFriends);
});
}
}