「良いコード/悪いコードで学ぶ設計入門 」のコレクションの章を勉強

# コレクションに関する設計技法

7.1わざわざ自前でコレクション処理を実装してしまう
7.2ループ処理中の条件分岐ネスト
7.3低凝集なコレクション処理
について、自分なりにサンプルソースを書きながら勉強しました。

国をコレクションとして扱い、各ランキングを出力するサンプルソースを実装しました。（国のデータは末尾の参考サイトを参照）

```java:データクラス
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Country {
  private int index;
  private String jpName;
  private String enName;
  private int population;
  private int area;
}
```

国クラスは、和名、英名、人口、面積をもちます。続いて、この国クラスを使って世界各国を作成するデータクラスです。

<details><summary>国のコレクションを作成するクラス</summary>

```java:データクラス
import java.util.ArrayList;
import java.util.List;

public class AllCountry {
  private List<Country> countryList;

  public AllCountry() {
    this.countryList = createCountryList();
  }

  private List<Country> createCountryList() {
    List<Country> countryList = new ArrayList<>();

    countryList.add(new Country(1, "アフガニスタン", "Afghanistan", 39618000, 652864));
    countryList.add(new Country(2, "アルバニア", "Albania", 2861000, 28748));
    countryList.add(new Country(3, "アルジェリア", "Algeria", 43812000, 2505742));
    countryList.add(new Country(4, "アンドラ", "Andorra", 78000, 468));
    countryList.add(new Country(5, "アンゴラ", "Angola", 33957000, 1246700));
    countryList.add(new Country(6, "アンティグア・バーブーダ", "Antigua and Barbuda", 92000, 442));
    countryList.add(new Country(7, "アルゼンチン", "Argentina", 45163000, 2780400));
    countryList.add(new Country(8, "アルメニア", "Armenia", 2798000, 29743));
    countryList.add(new Country(9, "オーストラリア", "Australia", 25795000, 7692024));
    countryList.add(new Country(10, "オーストリア", "Austria", 8914000, 83871));
    countryList.add(new Country(11, "アゼルバイジャン", "Azerbaijan", 10296000, 86600));
    countryList.add(new Country(12, "バハマ", "Bahamas", 407000, 13943));
    countryList.add(new Country(13, "バーレーン", "Bahrain", 1460000, 758));
    countryList.add(new Country(14, "バングラデシュ", "Bangladesh", 168414000, 147570));
    countryList.add(new Country(15, "バルバドス", "Barbados", 280000, 430));
    countryList.add(new Country(16, "ベラルーシ", "Belarus", 9606000, 207600));
    countryList.add(new Country(17, "ベルギー", "Belgium", 11582000, 30528));
    countryList.add(new Country(18, "ベリーズ", "Belize", 397000, 22966));
    countryList.add(new Country(19, "ベナン", "Benin", 12819000, 114763));
    countryList.add(new Country(20, "ブータン", "Bhutan", 775000, 38394));
    countryList.add(new Country(21, "ボリビア", "Bolivia", 775000, 1098581));
    countryList.add(new Country(22, "ボスニア・ヘルツェゴビナ", "Bosnia and Herzegovina", 3295000, 51209));
    countryList.add(new Country(23, "ボツワナ", "Botswana", 2569000, 582000));
    countryList.add(new Country(24, "ブラジル", "Brazil", 213827000, 8515767));
    countryList.add(new Country(25, "ブルネイ", "Brunei Darussalam", 443000, 5765));
    countryList.add(new Country(26, "ブルガリア", "Bulgaria", 6938000, 110879));
    countryList.add(new Country(27, "ブルキナファソ", "Burkina Faso", 21813000, 272967));
    countryList.add(new Country(28, "ブルンジ", "Burundi", 12386000, 27834));
    countryList.add(new Country(29, "カーボベルデ", "Cabo Verde", 585000, 4033));
    countryList.add(new Country(30, "カンボジア", "Cambodia", 16497000, 181035));
    countryList.add(new Country(31, "カメルーン", "Cameroon", 26845000, 475650));
    countryList.add(new Country(32, "カナダ", "Canada", 38019000, 9984670));
    countryList.add(new Country(33, "中央アフリカ共和国", "Central African Republic", 5414000, 622984));
    countryList.add(new Country(34, "チャド", "Chad", 16910000, 1284000));
    countryList.add(new Country(35, "チリ", "Chile", 19393000, 756102));
    countryList.add(new Country(36, "中国", "China", 1425861000, 9596960));
    countryList.add(new Country(37, "コロンビア", "Colombia", 51244000, 1141748));
    countryList.add(new Country(38, "コモロ", "Comoros", 814000, 1862));
    countryList.add(new Country(39, "コンゴ", "Congo (Republic of the)", 5769000, 342000));
    countryList.add(new Country(40, "コスタリカ", "Costa Rica", 5140000, 51100));
    countryList.add(new Country(41, "コートジボアール", "Cote d'Ivoire", 5140000, 322463));
    countryList.add(new Country(42, "クロアチア", "Croatia", 4079000, 56594));
    countryList.add(new Country(43, "キューバ", "Cuba", 11292000, 109884));
    countryList.add(new Country(44, "キプロス", "Cyprus", 1241000, 9251));
    countryList.add(new Country(45, "チェコ", "Czech Republic", 1241000, 78865));
    countryList.add(
        new Country(46, "朝鮮民主主義人民共和国", "Democratic People's Republic of Korea", 25921000, 120538));
    countryList.add(
        new Country(47, "コンゴ民主共和国", "Democratic Republic of the Congo", 94374000, 2389986));
    countryList.add(new Country(48, "デンマーク", "Denmark", 5840000, 43094));
    countryList.add(new Country(49, "ジブチ", "Djibouti", 1097000, 23200));
    countryList.add(new Country(50, "ドミニカ", "Dominica", 72000, 751));
    countryList.add(new Country(51, "ドミニカ共和国", "Dominican Republic", 11059000, 48671));
    countryList.add(new Country(52, "エクアドル", "Ecuador", 17690000, 256369));
    countryList.add(new Country(53, "エジプト", "Egypt", 108391000, 1001450));
    countryList.add(new Country(54, "エルサルバドル", "El Salvador", 6304000, 21041));
    countryList.add(new Country(55, "赤道ギニア", "Equatorial Guinea", 1613000, 28051));
    countryList.add(new Country(56, "エリトリア", "Eritrea", 3588000, 117600));
    countryList.add(new Country(57, "エストニア", "Estonia", 1329000, 45227));
    countryList.add(new Country(58, "エスワティニ", "Eswatini", 1187000, 17363));
    countryList.add(new Country(59, "エチオピア", "Ethiopia", 118743000, 1104300));
    countryList.add(new Country(60, "フィジ－", "Fiji", 922000, 18272));
    countryList.add(new Country(61, "フィンランド", "Finland", 5533000, 338431));
    countryList.add(new Country(62, "フランス", "France", 64502000, 551500));
    countryList.add(new Country(63, "ガボン", "Gabon", 2317000, 267668));
    countryList.add(new Country(64, "ガンビア", "Gambia", 2606000, 11295));
    countryList.add(new Country(65, "ジョージア", "Georgia", 3762000, 69700));
    countryList.add(new Country(66, "ドイツ", "Germany", 83390000, 357578));
    countryList.add(new Country(67, "ガーナ", "Ghana", 32511000, 238533));
    countryList.add(new Country(68, "ギリシャ", "Greece", 10481000, 131957));
    countryList.add(new Country(69, "グレナダ", "Grenada", 124000, 344));
    countryList.add(new Country(70, "グアテマラ", "Guatemala", 17494000, 108889));
    countryList.add(new Country(71, "ギニア", "Guinea", 13368000, 245857));
    countryList.add(new Country(72, "ギニアビサウ", "Guinea-Bissau", 2038000, 36125));
    countryList.add(new Country(73, "ガイアナ", "Guyana", 802000, 214969));
    countryList.add(new Country(74, "ハイチ", "Haiti", 11379000, 27750));
    countryList.add(new Country(75, "ホンジュラス", "Honduras", 10201000, 112492));
    countryList.add(new Country(76, "ハンガリ－", "Hungary", 9731000, 93027));
    countryList.add(new Country(77, "アイスランド", "Iceland", 368000, 103000));
    countryList.add(new Country(78, "インド", "India", 1402807000, 3287263));
    countryList.add(new Country(79, "インドネシア", "Indonesia", 272890000, 1904569));
    countryList.add(new Country(80, "イラン", "Iran", 272890000, 1628750));
    countryList.add(new Country(81, "イラク", "Iraq", 43071000, 435244));
    countryList.add(new Country(82, "アイルランド", "Ireland", 4967000, 69825));
    countryList.add(new Country(83, "イスラエル", "Israel", 8829000, 22072));
    countryList.add(new Country(84, "イタリア", "Italy", 59361000, 301336));
    countryList.add(new Country(85, "ジャマイカ", "Jamaica", 2826000, 10991));
    countryList.add(new Country(86, "日本", "Japan", 124946000, 377974));
    countryList.add(new Country(87, "ヨルダン", "Jordan", 11040000, 89328));
    countryList.add(new Country(88, "カザフスタン", "Kazakhstan", 19097000, 2724900));
    countryList.add(new Country(89, "ケニア", "Kenya", 52511000, 581313));
    countryList.add(new Country(90, "キリバス", "Kiribati", 127000, 726));
    countryList.add(new Country(91, "クウェート", "Kuwait", 4252000, 17818));
    countryList.add(new Country(92, "キルギスタン", "Kyrgyzstan", 6477000, 199951));
    countryList.add(
        new Country(93, "ラオス人民民主共和国", "Lao People's Democratic Republic", 7373000, 236800));
    countryList.add(new Country(94, "ラトビア", "Latvia", 1886000, 64562));
    countryList.add(new Country(95, "レバノン", "Lebanon", 5631000, 10452));
    countryList.add(new Country(96, "レソト", "Lesotho", 2268000, 30355));
    countryList.add(new Country(97, "リベリア", "Liberia", 5140000, 111369));
    countryList.add(new Country(98, "リビア", "Libya", 6695000, 1759540));
    countryList.add(new Country(99, "リヒテンシュタイン", "Liechtenstein", 38000, 160));
    countryList.add(new Country(100, "リトアニア", "Lithuania", 2804000, 65300));
    countryList.add(new Country(101, "ルクセンブルク", "Luxembourg", 634000, 2586));
    countryList.add(new Country(102, "マダガスカル", "Madagascar", 28571000, 587295));
    countryList.add(new Country(103, "マラウィ", "Malawi", 19633000, 118484));
    countryList.add(new Country(104, "マレーシア", "Malaysia", 33396000, 329847));
    countryList.add(new Country(105, "モルディブ", "Maldives", 517000, 300));
    countryList.add(new Country(106, "マリ", "Mali", 21561000, 1240192));
    countryList.add(new Country(107, "マルタ", "Malta", 521000, 316));
    countryList.add(new Country(108, "マーシャル諸島", "Marshall Islands", 42000, 181));
    countryList.add(new Country(109, "モーリタニア", "Mauritania", 4556000, 1030700));
    countryList.add(new Country(110, "モーリシャス", "Mauritius", 1298000, 1969));
    countryList.add(new Country(111, "メキシコ", "Mexico", 126386000, 1964375));
    countryList.add(new Country(112, "ミクロネシア連邦", "Micronesia (Federated States of)", 112000, 702));
    countryList.add(new Country(113, "モナコ", "Monaco", 36000, 2));
    countryList.add(new Country(114, "モンゴル", "Mongolia", 3322000, 1564116));
    countryList.add(new Country(115, "モンテネグロ", "Montenegro", 628000, 13812));
    countryList.add(new Country(116, "モロッコ", "Morocco", 36888000, 446550));
    countryList.add(new Country(117, "モザンビーク", "Mozambique", 31635000, 801590));
    countryList.add(new Country(118, "ミャンマー", "Myanmar", 53618000, 676886));
    countryList.add(new Country(119, "ナミビア", "Namibia", 2511000, 824268));
    countryList.add(new Country(120, "ナウル", "Nauru", 12000, 21));
    countryList.add(new Country(121, "ネパール", "Nepal", 29698000, 147181));
    countryList.add(new Country(122, "オランダ", "Netherlands", 17466000, 37354));
    countryList.add(new Country(123, "ニュージーランド", "New Zealand", 5095000, 270467));
    countryList.add(new Country(124, "ニカラグア", "Nicaragua", 6802000, 130373));
    countryList.add(new Country(125, "ニジェール", "Niger", 24785000, 1267000));
    countryList.add(new Country(126, "ナイジェリア", "Nigeria", 210874000, 923768));
    countryList.add(new Country(127, "北マケドニア", "North Macedonia", 2108000, 25713));
    countryList.add(new Country(128, "ノルウェー", "Norway", 5391000, 385207));
    countryList.add(new Country(129, "オマーン", "Oman", 4497000, 309500));
    countryList.add(new Country(130, "パキスタン", "Pakistan", 229280000, 796095));
    countryList.add(new Country(131, "パラオ", "Palau", 17000, 459));
    countryList.add(new Country(132, "パナマ", "Panama", 4323000, 75417));
    countryList.add(new Country(133, "パプア・ニューギニア", "Papua New Guinea", 9850000, 462840));
    countryList.add(new Country(134, "パラグアイ", "Paraguay", 6664000, 406752));
    countryList.add(new Country(135, "ペルー", "Peru", 33519000, 1285216));
    countryList.add(new Country(136, "フィリピン", "Philippines", 113094000, 300000));
    countryList.add(new Country(137, "ポーランド", "Poland", 38378000, 311888));
    countryList.add(new Country(138, "ポルトガル", "Portugal", 10297000, 92212));
    countryList.add(new Country(139, "カタール", "Qatar", 2692000, 11607));
    countryList.add(new Country(140, "韓国", "Republic of Korea", 51831000, 100033));
    countryList.add(new Country(141, "モルドバ", "Republic of Moldova", 3074000, 33846));
    countryList.add(new Country(142, "ルーマニア", "Romania", 19394000, 238391));
    countryList.add(new Country(143, "ロシア", "Russian Federation", 145472000, 17124442));
    countryList.add(new Country(144, "ルワンダ", "Rwanda", 13305000, 26340));
    countryList.add(new Country(145, "セントクリストファー・ネイビス", "Saint Kitts and Nevis", 47000, 261));
    countryList.add(new Country(146, "セントルシア", "Saint Lucia", 179000, 539));
    countryList.add(
        new Country(147, "セントビンセントおよびグレナディーン諸島", "Saint Vincent and the Grenadines", 104000, 389));
    countryList.add(new Country(148, "サモア", "Samoa", 216000, 2842));
    countryList.add(new Country(149, "サンマリノ", "San Marino", 33000, 61));
    countryList.add(new Country(150, "サントメ・プリンシペ", "Sao Tome and Principe", 221000, 964));
    countryList.add(new Country(151, "サウジアラビア", "Saudi Arabia", 35764000, 2149690));
    countryList.add(new Country(152, "セネガル", "Senegal", 16656000, 196712));
    countryList.add(new Country(153, "セルビア", "Serbia", 7331000, 88361));
    countryList.add(new Country(154, "セイシェル", "Seychelles", 106000, 452));
    countryList.add(new Country(155, "シエラレオネ", "Sierra Leone", 8327000, 72300));
    countryList.add(new Country(156, "シンガポール", "Singapore", 5926000, 714));
    countryList.add(new Country(157, "スロバキア", "Slovakia", 5455000, 49036));
    countryList.add(new Country(158, "スロベニア", "Slovenia", 2119000, 20273));
    countryList.add(new Country(159, "ソロモン諸島", "Solomon Islands", 699000, 28896));
    countryList.add(new Country(160, "ソマリア", "Somalia", 16801000, 637657));
    countryList.add(new Country(161, "南アフリカ", "South Africa", 59137000, 1221037));
    countryList.add(new Country(162, "南スーダン", "South Sudan", 10667000, 644329));
    countryList.add(new Country(163, "スペイン", "Spain", 47397000, 505992));
    countryList.add(new Country(164, "スリランカ", "Sri Lanka", 21746000, 65610));
    countryList.add(new Country(165, "スーダン", "Sudan", 45052000, 1861484));
    countryList.add(new Country(166, "スリナム", "Suriname", 610000, 163820));
    countryList.add(new Country(167, "スウェーデン", "Sweden", 10416000, 450295));
    countryList.add(new Country(168, "スイス", "Switzerland", 8670000, 41285));
    countryList.add(new Country(169, "シリア", "Syria", 8670000, 185180));
    countryList.add(new Country(170, "タジキスタン", "Tajikistan", 9643000, 143100));
    countryList.add(new Country(171, "タイ", "Thailand", 71561000, 513120));
    countryList.add(new Country(172, "東ティモール", "Timor-Leste", 1310000, 14919));
    countryList.add(new Country(173, "トーゴ", "Togo", 8542000, 56785));
    countryList.add(new Country(174, "トンガ", "Tonga", 105000, 747));
    countryList.add(new Country(175, "トリニダード・トバゴ", "Trinidad and Tobago", 1522000, 5130));
    countryList.add(new Country(176, "チュニジア", "Tunisia", 12217000, 163610));
    countryList.add(new Country(177, "トルコ", "Turkey", 12217000, 783562));
    countryList.add(new Country(178, "トルクメニスタン", "Turkmenistan", 6296000, 488100));
    countryList.add(new Country(179, "ツバル", "Tuvalu", 11000, 26));
    countryList.add(new Country(180, "ウガンダ", "Uganda", 45123000, 241550));
    countryList.add(new Country(181, "ウクライナ", "Ukraine", 43728000, 603500));
    countryList.add(new Country(182, "アラブ首長国連邦", "United Arab Emirates", 9327000, 83600));
    countryList.add(new Country(183, "イギリス", "United Kingdom", 67167000, 242495));
    countryList.add(new Country(184, "タンザニア", "United Republic of Tanzania", 62637000, 945087));
    countryList.add(new Country(185, "アメリカ", "United States of America", 336495000, 9631420));
    countryList.add(new Country(186, "ウルグアイ", "Uruguay", 3429000, 176215));
    countryList.add(new Country(187, "ウズベキスタン", "Uzbekistan", 33809000, 449000));
    countryList.add(new Country(188, "バヌアツ", "Vanuatu", 315000, 12189));
    countryList.add(new Country(189, "ベネズエラ", "Venezuela", 315000, 916445));
    countryList.add(new Country(190, "ベトナム", "Viet Nam", 97093000, 331212));
    countryList.add(new Country(191, "イエメン", "Yemen", 32640000, 527968));
    countryList.add(new Country(192, "ザンビア", "Zambia", 19200000, 752612));
    countryList.add(new Country(193, "ジンバブエ", "Zimbabwe", 15834000, 390757));

    return countryList;
  }

  public List<Country> getCountryList() {
    return List.copyOf(this.countryList);
  }
}
```
</details>

長いので折りたたんでいます。データは国連の情報(2021年版）です。
次にコレクションに格納した国を操作するクラスです。

```java:国（コレクション）を操作してランクを表示するクラス
import org.apache.commons.collections4.ListUtils;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class RankByCountry {

  private final List<Country> countryList;

  public RankByCountry() {
    this.countryList = new AllCountry().getCountryList();
  }

  public void run() {
    String targetCountry = "日本";
    boolean isJapanBook = hasCountry1(countryList, targetCountry);
    System.out.println("存在チェック　リストに" + targetCountry + ":" + isJapanBook);

    boolean isJapanBook2 = hasCountry2(countryList, targetCountry);
    System.out.println("存在チェック　リストに" + targetCountry + ":" + isJapanBook2);

    // 国を10ごとに分割してそれぞれをforEachで表示
    System.out.println();
    System.out.println("すべての国を表示");
    List<List<Country>> country10List = partition10Country(countryList);
    for (List<Country> countries : country10List) {
      countries.forEach(
          country ->
              System.out.println(
                  country.getIndex() + ":" + country.getJpName() + "," + country.getEnName()));
    }
    int rank = 15;
    // xxではじまる国は？
    System.out.println();
    testTargetCountryList(countryList);
    // 人口の表示
    System.out.println();
    System.out.println("人口ランキング");
    List<Country> countryListTo10 = getPopulationTopCountryList(countryList, rank);
    printCountryList(countryListTo10);

    // 面積の表示
    System.out.println();
    System.out.println("面積ランキング");
    List<Country> areaTo15List = getAreaTopCountryList(countryList, rank);
    printCountryList(areaTo15List);
    // 人口密度
    System.out.println();
    System.out.println("人口密度ランキング");
    List<Country> populationDensityTo15List =
        getPopulationDensityTop15CountryList(countryList, rank);
    printCountryList(populationDensityTo15List);

    // 条件で絞り込み
    System.out.println();
    System.out.println(" 存在感のある国 .... 人口が" + rank + "位以内 かつ　面積が" + rank + "位以内　かつ　国名の長さが5文字以内の国");

    List<Country> topCountryList = getPresenceCountryList(countryList, rank);
    printCountryList(topCountryList);
  }

  private boolean hasCountry1(List<Country> countryList, String searchBookName) {
    boolean hasTargetBook = false;
    for (Country country : countryList) {
      if (country.getJpName().equals(searchBookName)) {
        hasTargetBook = true;
        break;
      }
    }
    return hasTargetBook;
  }

  private boolean hasCountry2(List<Country> countryList, String searchBookName) {
    return countryList.stream().anyMatch(country -> country.getJpName().equals(searchBookName));
  }

  // 10毎のグループにわける
  private List<List<Country>> partition10Country(List<Country> countryList) {
    return ListUtils.partition(countryList, 10);
  }

  // Listの中からtargetPrefixで始まる国を探し、その国リストを返す
  private List<Country> getTargetCountryList(List<Country> countryList, String targetPrefix) {
    List<Country> targetCountryList = new ArrayList<>();
    String regex = "^.*" + targetPrefix + "+";
    Pattern pattern = Pattern.compile(regex);
    for (Country country : countryList) {
      // 正規表現になおす
      Matcher matcher = pattern.matcher(country.getEnName());
      if (matcher.find()) {
        targetCountryList.add(country);
      }
    }
    return targetCountryList;
  }

  private List<Country> getTargetCountryList2(List<Country> countryList, String targetPrefix) {
    return countryList.stream()
        .filter(country -> country.getEnName().startsWith(targetPrefix))
        .sorted(Comparator.comparing(Country::getEnName).reversed())
        .collect(Collectors.toList());
  }

  private void testTargetCountryList(List<Country> countryList) {
    // Jではじまる国リストを取得する
    String targetPrefix = "str";
    System.out.println(targetPrefix + "を含む国は？");
    List<Country> countries = getTargetCountryList(countryList, targetPrefix);
    countries.forEach(
        co -> System.out.println(co.getIndex() + ":" + co.getJpName() + "," + co.getEnName()));

    // 別の方法stream
    targetPrefix = "Be";
    System.out.println();
    System.out.println(targetPrefix + "ではじまる国は？");
    List<Country> countries2 = getTargetCountryList2(countryList, targetPrefix);
    countries2.forEach(
        co -> System.out.println(co.getIndex() + ":" + co.getJpName() + "," + co.getEnName()));
  }

  // 人口が多い上位の国を表示
  private List<Country> getPopulationTopCountryList(List<Country> countryList, int rank) {
    return countryList.stream()
        .sorted(Comparator.comparing(Country::getPopulation).reversed())
        .limit(rank)
        .collect(Collectors.toList());
  }

  private void printCountryList(List<Country> countryList) {
    AtomicInteger i = new AtomicInteger(1);
    DecimalFormat decFormat = new DecimalFormat("###,###");
    countryList.forEach(
        country ->
            System.out.println(
                i.getAndIncrement()
                    + ":"
                    + country.getJpName()
                    + " 人口:"
                    + decFormat.format(country.getPopulation())
                    + " 面積(km^2):"
                    + decFormat.format(country.getArea())
                    + " 国別人口密度(人/km^2):"
                    + decFormat.format(country.getPopulation() / country.getArea())));
  }

  // 面積が多い上位の国を表示
  private List<Country> getAreaTopCountryList(List<Country> countryList, int rank) {
    return countryList.stream()
        .sorted(Comparator.comparing(Country::getArea).reversed())
        .limit(rank)
        .collect(Collectors.toList());
  }

  // 人口密度が多い上位の国を表示
  private List<Country> getPopulationDensityTop15CountryList(List<Country> countryList, int rank) {
    return countryList.stream()
        .sorted(Comparator.comparing((Country co) -> co.getPopulation() / co.getArea()).reversed())
        .limit(rank)
        .collect(Collectors.toList());
  }

  // 国の中で以下の条件を満たすものを抽出
  // 人口が上位rank位以内
  // 面積が上位rank位以内
  // 国名の長さが5文字以内
  private List<Country> getPresenceCountryList(List<Country> countryList, int rank) {
    // 人口が50位以内の国リスト1
    List<Country> topPopulationCountries = getPopulationTopCountryList(countryList, rank);

    // 面積が50位以内の国リスト2
    List<Country> topAreaCountries = getAreaTopCountryList(countryList, rank);

    // 国名の長さが5文字以内の国 50位のリスト3
    List<Country> length5Countries = getlength5TopCountryList(countryList);

    // リスト1とリスト2を比較する
    List<Country> list1and2 = ListUtils.intersection(topPopulationCountries, topAreaCountries);
    List<Country> list1and2and3 = ListUtils.intersection(list1and2, length5Countries);

    // sort
    list1and2and3 =
        list1and2and3.stream()
            .sorted(Comparator.comparing(Country::getPopulation).reversed())
            .collect(Collectors.toList());

    return list1and2and3;
  }

  private List<Country> getlength5TopCountryList(List<Country> countryList) {
    return countryList.stream()
        .filter(country -> country.getJpName().length() <= 5)
        .collect(Collectors.toList());
  }
}
```
mainメソッドなどからrunメソッドを実行してください。

---
# 実行結果

標準ライブラリのanyMatchメソッドを使ったサンプルを作成して、動作確認してみました。
悪いコード：hasCountry1()for文でループして、引数で指定された国があるか探しています。
良いコード：hasCountry2()標準ライブラリのanyMatchを使って、引数の国があるか探しています。標準ライブラリの方が簡単ですね。

また、ループ処理中の条件分岐ネストを確認しようとして・・・・
国のグループを以下の３条件の集合に分けて、３つとも条件を満たすものを探す処理を作ってみました。

<dl>
  <dt>条件1</dt>
  <dd>人口が上位ランクの国</dd>
  <dt>条件2</dt>
  <dd>国土が上位ランクの国</dd>
  <dt>条件3</dt>
  <dd>国名の長さが５文字以内の国</dd>
</dl>

当初ここでfor文のループを使った悪いコードを作成しようとしていたのですが、時間の無駄に思えて断念。
ListUtils.intersection()を使って、すべての条件を満たすものを抽出しました。
⇒積集合 A ∩ B ∩ Cが簡単にできて便利でした。３つの条件を満たすものを、勝手に、存在感のある国と定義して抽出してみました。

低凝集なコレクション処理となるよう、ファーストクラスコレクションのパターンとなるようコレクションに関するロジックをカプセル化しました。
⇒RankByCountryクラス参照

変更しやすいクラス設計について、コレクションでの理解を深めることができました。


```:実行結果
存在チェック　リストに日本:true
存在チェック　リストに日本:true

すべての国を表示
1:アフガニスタン,Afghanistan
2:アルバニア,Albania
3:アルジェリア,Algeria
4:アンドラ,Andorra
5:アンゴラ,Angola
6:アンティグア・バーブーダ,Antigua and Barbuda
7:アルゼンチン,Argentina
8:アルメニア,Armenia
9:オーストラリア,Australia
10:オーストリア,Austria
11:アゼルバイジャン,Azerbaijan
12:バハマ,Bahamas
13:バーレーン,Bahrain
14:バングラデシュ,Bangladesh
15:バルバドス,Barbados
16:ベラルーシ,Belarus
17:ベルギー,Belgium
18:ベリーズ,Belize
19:ベナン,Benin
20:ブータン,Bhutan
21:ボリビア,Bolivia
22:ボスニア・ヘルツェゴビナ,Bosnia and Herzegovina
23:ボツワナ,Botswana
24:ブラジル,Brazil
25:ブルネイ,Brunei Darussalam
26:ブルガリア,Bulgaria
27:ブルキナファソ,Burkina Faso
28:ブルンジ,Burundi
29:カーボベルデ,Cabo Verde
30:カンボジア,Cambodia
31:カメルーン,Cameroon
32:カナダ,Canada
33:中央アフリカ共和国,Central African Republic
34:チャド,Chad
35:チリ,Chile
36:中国,China
37:コロンビア,Colombia
38:コモロ,Comoros
39:コンゴ,Congo (Republic of the)
40:コスタリカ,Costa Rica
41:コートジボアール,Cote d'Ivoire
42:クロアチア,Croatia
43:キューバ,Cuba
44:キプロス,Cyprus
45:チェコ,Czech Republic
46:朝鮮民主主義人民共和国,Democratic People's Republic of Korea
47:コンゴ民主共和国,Democratic Republic of the Congo
48:デンマーク,Denmark
49:ジブチ,Djibouti
50:ドミニカ,Dominica
51:ドミニカ共和国,Dominican Republic
52:エクアドル,Ecuador
53:エジプト,Egypt
54:エルサルバドル,El Salvador
55:赤道ギニア,Equatorial Guinea
56:エリトリア,Eritrea
57:エストニア,Estonia
58:エスワティニ,Eswatini
59:エチオピア,Ethiopia
60:フィジ－,Fiji
61:フィンランド,Finland
62:フランス,France
63:ガボン,Gabon
64:ガンビア,Gambia
65:ジョージア,Georgia
66:ドイツ,Germany
67:ガーナ,Ghana
68:ギリシャ,Greece
69:グレナダ,Grenada
70:グアテマラ,Guatemala
71:ギニア,Guinea
72:ギニアビサウ,Guinea-Bissau
73:ガイアナ,Guyana
74:ハイチ,Haiti
75:ホンジュラス,Honduras
76:ハンガリ－,Hungary
77:アイスランド,Iceland
78:インド,India
79:インドネシア,Indonesia
80:イラン,Iran
81:イラク,Iraq
82:アイルランド,Ireland
83:イスラエル,Israel
84:イタリア,Italy
85:ジャマイカ,Jamaica
86:日本,Japan
87:ヨルダン,Jordan
88:カザフスタン,Kazakhstan
89:ケニア,Kenya
90:キリバス,Kiribati
91:クウェート,Kuwait
92:キルギスタン,Kyrgyzstan
93:ラオス人民民主共和国,Lao People's Democratic Republic
94:ラトビア,Latvia
95:レバノン,Lebanon
96:レソト,Lesotho
97:リベリア,Liberia
98:リビア,Libya
99:リヒテンシュタイン,Liechtenstein
100:リトアニア,Lithuania
101:ルクセンブルク,Luxembourg
102:マダガスカル,Madagascar
103:マラウィ,Malawi
104:マレーシア,Malaysia
105:モルディブ,Maldives
106:マリ,Mali
107:マルタ,Malta
108:マーシャル諸島,Marshall Islands
109:モーリタニア,Mauritania
110:モーリシャス,Mauritius
111:メキシコ,Mexico
112:ミクロネシア連邦,Micronesia (Federated States of)
113:モナコ,Monaco
114:モンゴル,Mongolia
115:モンテネグロ,Montenegro
116:モロッコ,Morocco
117:モザンビーク,Mozambique
118:ミャンマー,Myanmar
119:ナミビア,Namibia
120:ナウル,Nauru
121:ネパール,Nepal
122:オランダ,Netherlands
123:ニュージーランド,New Zealand
124:ニカラグア,Nicaragua
125:ニジェール,Niger
126:ナイジェリア,Nigeria
127:北マケドニア,North Macedonia
128:ノルウェー,Norway
129:オマーン,Oman
130:パキスタン,Pakistan
131:パラオ,Palau
132:パナマ,Panama
133:パプア・ニューギニア,Papua New Guinea
134:パラグアイ,Paraguay
135:ペルー,Peru
136:フィリピン,Philippines
137:ポーランド,Poland
138:ポルトガル,Portugal
139:カタール,Qatar
140:韓国,Republic of Korea
141:モルドバ,Republic of Moldova
142:ルーマニア,Romania
143:ロシア,Russian Federation
144:ルワンダ,Rwanda
145:セントクリストファー・ネイビス,Saint Kitts and Nevis
146:セントルシア,Saint Lucia
147:セントビンセントおよびグレナディーン諸島,Saint Vincent and the Grenadines
148:サモア,Samoa
149:サンマリノ,San Marino
150:サントメ・プリンシペ,Sao Tome and Principe
151:サウジアラビア,Saudi Arabia
152:セネガル,Senegal
153:セルビア,Serbia
154:セイシェル,Seychelles
155:シエラレオネ,Sierra Leone
156:シンガポール,Singapore
157:スロバキア,Slovakia
158:スロベニア,Slovenia
159:ソロモン諸島,Solomon Islands
160:ソマリア,Somalia
161:南アフリカ,South Africa
162:南スーダン,South Sudan
163:スペイン,Spain
164:スリランカ,Sri Lanka
165:スーダン,Sudan
166:スリナム,Suriname
167:スウェーデン,Sweden
168:スイス,Switzerland
169:シリア,Syria
170:タジキスタン,Tajikistan
171:タイ,Thailand
172:東ティモール,Timor-Leste
173:トーゴ,Togo
174:トンガ,Tonga
175:トリニダード・トバゴ,Trinidad and Tobago
176:チュニジア,Tunisia
177:トルコ,Turkey
178:トルクメニスタン,Turkmenistan
179:ツバル,Tuvalu
180:ウガンダ,Uganda
181:ウクライナ,Ukraine
182:アラブ首長国連邦,United Arab Emirates
183:イギリス,United Kingdom
184:タンザニア,United Republic of Tanzania
185:アメリカ,United States of America
186:ウルグアイ,Uruguay
187:ウズベキスタン,Uzbekistan
188:バヌアツ,Vanuatu
189:ベネズエラ,Venezuela
190:ベトナム,Viet Nam
191:イエメン,Yemen
192:ザンビア,Zambia
193:ジンバブエ,Zimbabwe

strを含む国は？
9:オーストラリア,Australia
10:オーストリア,Austria

Beではじまる国は？
19:ベナン,Benin
18:ベリーズ,Belize
17:ベルギー,Belgium
16:ベラルーシ,Belarus

人口ランキング
1:中国 人口:1,425,861,000 面積(km^2):9,596,960 国別人口密度(人/km^2):148
2:インド 人口:1,402,807,000 面積(km^2):3,287,263 国別人口密度(人/km^2):426
3:アメリカ 人口:336,495,000 面積(km^2):9,631,420 国別人口密度(人/km^2):34
4:インドネシア 人口:272,890,000 面積(km^2):1,904,569 国別人口密度(人/km^2):143
5:イラン 人口:272,890,000 面積(km^2):1,628,750 国別人口密度(人/km^2):167
6:パキスタン 人口:229,280,000 面積(km^2):796,095 国別人口密度(人/km^2):288
7:ブラジル 人口:213,827,000 面積(km^2):8,515,767 国別人口密度(人/km^2):25
8:ナイジェリア 人口:210,874,000 面積(km^2):923,768 国別人口密度(人/km^2):228
9:バングラデシュ 人口:168,414,000 面積(km^2):147,570 国別人口密度(人/km^2):1,141
10:ロシア 人口:145,472,000 面積(km^2):17,124,442 国別人口密度(人/km^2):8
11:メキシコ 人口:126,386,000 面積(km^2):1,964,375 国別人口密度(人/km^2):64
12:日本 人口:124,946,000 面積(km^2):377,974 国別人口密度(人/km^2):330
13:エチオピア 人口:118,743,000 面積(km^2):1,104,300 国別人口密度(人/km^2):107
14:フィリピン 人口:113,094,000 面積(km^2):300,000 国別人口密度(人/km^2):376
15:エジプト 人口:108,391,000 面積(km^2):1,001,450 国別人口密度(人/km^2):108

面積ランキング
1:ロシア 人口:145,472,000 面積(km^2):17,124,442 国別人口密度(人/km^2):8
2:カナダ 人口:38,019,000 面積(km^2):9,984,670 国別人口密度(人/km^2):3
3:アメリカ 人口:336,495,000 面積(km^2):9,631,420 国別人口密度(人/km^2):34
4:中国 人口:1,425,861,000 面積(km^2):9,596,960 国別人口密度(人/km^2):148
5:ブラジル 人口:213,827,000 面積(km^2):8,515,767 国別人口密度(人/km^2):25
6:オーストラリア 人口:25,795,000 面積(km^2):7,692,024 国別人口密度(人/km^2):3
7:インド 人口:1,402,807,000 面積(km^2):3,287,263 国別人口密度(人/km^2):426
8:アルゼンチン 人口:45,163,000 面積(km^2):2,780,400 国別人口密度(人/km^2):16
9:カザフスタン 人口:19,097,000 面積(km^2):2,724,900 国別人口密度(人/km^2):7
10:アルジェリア 人口:43,812,000 面積(km^2):2,505,742 国別人口密度(人/km^2):17
11:コンゴ民主共和国 人口:94,374,000 面積(km^2):2,389,986 国別人口密度(人/km^2):39
12:サウジアラビア 人口:35,764,000 面積(km^2):2,149,690 国別人口密度(人/km^2):16
13:メキシコ 人口:126,386,000 面積(km^2):1,964,375 国別人口密度(人/km^2):64
14:インドネシア 人口:272,890,000 面積(km^2):1,904,569 国別人口密度(人/km^2):143
15:スーダン 人口:45,052,000 面積(km^2):1,861,484 国別人口密度(人/km^2):24

人口密度ランキング
1:モナコ 人口:36,000 面積(km^2):2 国別人口密度(人/km^2):18,000
2:シンガポール 人口:5,926,000 面積(km^2):714 国別人口密度(人/km^2):8,299
3:バーレーン 人口:1,460,000 面積(km^2):758 国別人口密度(人/km^2):1,926
4:モルディブ 人口:517,000 面積(km^2):300 国別人口密度(人/km^2):1,723
5:マルタ 人口:521,000 面積(km^2):316 国別人口密度(人/km^2):1,648
6:バングラデシュ 人口:168,414,000 面積(km^2):147,570 国別人口密度(人/km^2):1,141
7:モーリシャス 人口:1,298,000 面積(km^2):1,969 国別人口密度(人/km^2):659
8:バルバドス 人口:280,000 面積(km^2):430 国別人口密度(人/km^2):651
9:ナウル 人口:12,000 面積(km^2):21 国別人口密度(人/km^2):571
10:サンマリノ 人口:33,000 面積(km^2):61 国別人口密度(人/km^2):540
11:レバノン 人口:5,631,000 面積(km^2):10,452 国別人口密度(人/km^2):538
12:韓国 人口:51,831,000 面積(km^2):100,033 国別人口密度(人/km^2):518
13:ルワンダ 人口:13,305,000 面積(km^2):26,340 国別人口密度(人/km^2):505
14:オランダ 人口:17,466,000 面積(km^2):37,354 国別人口密度(人/km^2):467
15:ブルンジ 人口:12,386,000 面積(km^2):27,834 国別人口密度(人/km^2):444

 存在感のある国 .... 人口が15位以内 かつ　面積が15位以内　かつ　国名の長さが5文字以内の国
1:中国 人口:1,425,861,000 面積(km^2):9,596,960 国別人口密度(人/km^2):148
2:インド 人口:1,402,807,000 面積(km^2):3,287,263 国別人口密度(人/km^2):426
3:アメリカ 人口:336,495,000 面積(km^2):9,631,420 国別人口密度(人/km^2):34
4:ブラジル 人口:213,827,000 面積(km^2):8,515,767 国別人口密度(人/km^2):25
5:ロシア 人口:145,472,000 面積(km^2):17,124,442 国別人口密度(人/km^2):8
6:メキシコ 人口:126,386,000 面積(km^2):1,964,375 国別人口密度(人/km^2):64

```

ListUtilsを利用するためのmaven設定。
```xml:pom.xml
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.1</version>
        </dependency>
    </dependencies>
```

:::note info
「7.3.2外部へ渡す場合はコレクションを変更できなくする」の章でunmodifiableList()が紹介されていますが、これはjava8までで、
java11では以下のようにList.copyOf()を使うようでした。intelliJにSpotBugsを導入して実行すると、そのまま返すとセキュリティ的にダメと怒られました。
```java:
  public List<Country> getCountryList() {
    return List.copyOf(this.countryList);
  }
```
:::

まったくの余談ですが、国連データから、国名と人口のデータを抽出したあと、別サイトから国の面積をひっぱてきてエクセルvlookup等を使って国名のつきあわせをしたのですが、微妙に国名がマッチせず、苦労しました。名前が似ている２つの国の突合せには、苦労しました。（例：コンゴ共和国、コンゴ民主共和国、セイシェル、セーシェル、マラウイ、マラウィ、キルギスタン、キルギス共和国）

参考サイト：
国連（世界の人口）
https://population.un.org/wpp/

国の面積順リスト
https://ja.wikipedia.org/wiki/%E5%9B%BD%E3%81%AE%E9%9D%A2%E7%A9%8D%E9%A0%86%E3%83%AA%E3%82%B9%E3%83%88

ファーストクラスコレクションとは
https://shozo-gson.com/first-class-collection/

変更不可なリストを作成する方法
https://kita-note.com/java-immutable-list