質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

Java8のstreamで、自作オブジェクトのListの並べ替えをしたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,443

omodai

score 10

前提・実現したいこと

Java8のStreamを使用して自作オブジェクトのListの並べ替えをしたいと考えています
テストとして、PersonクラスとSectionクラス、その二つを持っているInfoクラスを作りました

  • Personクラス
package sorttest;

public class Person {

    String firstName;
    String lastName;
    int age;

    public Person(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" + "firstName=" + firstName + ", lastName=" + lastName + ", age=" + age + '}';
    }
}
  • Sectionクラス
package sorttest;

public class Section {

    String sectionCode;
    String sectionName;

    public Section(String sectionCode, String sectionName) {
        this.sectionCode = sectionCode;
        this.sectionName = sectionName;
    }

    public String getSectionCode() {
        return sectionCode;
    }

    public String getSectionName() {
        return sectionName;
    }

    @Override
    public String toString() {
        return "Section{" + "sectionCode=" + sectionCode + ", sectionName=" + sectionName + '}';
    }
}
  • Infoクラス
package sorttest;

public class Info {

    Person person;
    Section section;

    public Info(Person person, Section section) {
        this.person = person;
        this.section = section;
    }

    public Person getPerson() {
        return person;
    }

    public Section getSection() {
        return section;
    }

    @Override
    public String toString() {
        return "Info{" + "person=" + person.toString() + ", section=" + section.toString() + '}';
    }
}

実行したソースコード

以下の様に単純な形のリストだとStreamでcomparingを使用して並び替えができます

package sorttest;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class SortTest {

    public static void main(String[] args) {

        List<Section> sectionList = new ArrayList<>();

        sectionList.add(new Section("A", "あああ"));
        sectionList.add(new Section("C", "ううう"));
        sectionList.add(new Section("D", "えええ"));
        sectionList.add(new Section("B", "ううう"));


        System.out.println("sectionListをループ");
        for (Section section : sectionList) {
            System.out.println(section.toString());
        }

        System.out.println("-------------------------------------------------------");
        System.out.println("-------------------------------------------------------");
        System.out.println("-------------------------------------------------------");

        System.out.println("sectionListをsectionNameでソートしてからループ");

        List<Section> sectionList2 = new ArrayList<>();
        sectionList2.addAll(sectionList.stream().sorted(
                Comparator.comparing(Section::getSectionCode))
                .collect(Collectors.toList()));
        for (Section section : sectionList2) {
            System.out.println(section.toString());
        }
}
  • 実行結果
sectionListをループ
Section{sectionCode=A, sectionName=あああ}
Section{sectionCode=C, sectionName=ううう}
Section{sectionCode=D, sectionName=えええ}
Section{sectionCode=B, sectionName=ううう}
-------------------------------------------------------
-------------------------------------------------------
-------------------------------------------------------
sectionListをsectionNameでソートしてからループ
Section{sectionCode=A, sectionName=あああ}
Section{sectionCode=B, sectionName=ううう}
Section{sectionCode=C, sectionName=ううう}
Section{sectionCode=D, sectionName=えええ}

はまっているところ

以下のようにInfoオブジェクトの中にあるSectionオブジェクトの複数フィールドでソートしたい場合はどうするのがいいのでしょうか?

package sorttest;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class SortTest {

    public static void main(String[] args) {
        System.out.println("infoListをループ");
        List<Info> infoList = new ArrayList<>();
        infoList.add(new Info(new Person("taro", "yamada", 30), new Section("A", "あああ")));
        infoList.add(new Info(new Person("sachiko", "sato", 28), new Section("C", "ううう")));
        infoList.add(new Info(new Person("ichiro", "suzuki", 40), new Section("D", "えええ")));
        infoList.add(new Info(new Person("Eri", "ito", 20), new Section("B", "ううう")));

        for (Info info : infoList) {
            System.out.println(info.getPerson().toString());
            System.out.println(info.getSection().toString());
            System.out.println("-------------------------------------------------------");
        }
    }
}
  • 実行結果
infoListをループ
Person{firstName=taro, lastName=yamada, age=30}
Section{sectionCode=A, sectionName=あああ}
-------------------------------------------------------
Person{firstName=sachiko, lastName=sato, age=28}
Section{sectionCode=C, sectionName=ううう}
-------------------------------------------------------
Person{firstName=ichiro, lastName=suzuki, age=40}
Section{sectionCode=D, sectionName=えええ}
-------------------------------------------------------
Person{firstName=Eri, lastName=ito, age=20}
Section{sectionCode=B, sectionName=ううう}
-------------------------------------------------------
  • SectionのsectionNameでソートして以下のようにしたい
  • 追記・・・sectionNameだけでなくsectionCodeと合わせてソートするにはどうすればいいでしょうか?
Person{firstName=taro, lastName=yamada, age=30}
Section{sectionCode=A, sectionName=あああ}
-------------------------------------------------------
Person{firstName=Eri, lastName=ito, age=20}
Section{sectionCode=B, sectionName=ううう}
-------------------------------------------------------
Person{firstName=sachiko, lastName=sato, age=28}
Section{sectionCode=C, sectionName=ううう}
-------------------------------------------------------
Person{firstName=ichiro, lastName=suzuki, age=40}
Section{sectionCode=D, sectionName=えええ}
-------------------------------------------------------
  • よろしくお願いします。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

List<Info> sortedList = infoList.stream()
        .sorted(Comparator.comparing(info -> info.getSection().getSectionName()))
        .collect(Collectors.toList());

追記

Comparator<Info> comparator = Comparator.<Info, String> comparing(info -> info.getSection().getSectionName())
        .thenComparing(info -> info.getSection().getSectionCode());

List<Info> sortedList = infoList.stream()
        .sorted(comparator)
        .collect(Collectors.toList());

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/13 19:46

    早速の回答ありがとうございます。
    上記の記述でうまくいきました!!

    質問の抜けがありました。
    sectionName,sectionCodeの複合でソートしたい場合はどうすればいいかご存知でしょうか?

    キャンセル

  • 2017/07/13 20:23

    追記しました。
    いい加減長いんで、Comparatorの部分を独立させましたが、ワンライナーで書きたければどうぞ。

    キャンセル

  • 2017/07/14 08:59

    やりたいことができました。ありがとうございました!

    キャンセル

+2

Infoクラスにimplements Comparableすればいいのでは?

public class Info implements Comparable<Info> {

    public int compareTo(Info info) {
        int i = this.section.getSectionName().compareTo(info.section.getSectionName());
        return i == 0 ? this.section.getSectionCode().compareTo(info.section.getSectionCode()) : i;
    }

}


こうすればソートはこうなります。

List<Info> sortedList = infoList.stream().sorted().collect(Collectors.toList());

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る