たま

技術的なメモ置き場。主にJava。

Comparatorでソート

Comparatorを使用して、JavaBeanのリストをソートする。

使用するJavaBean

public class Student {
    private int id;
    private String name;
    private int age;
    // getter/setter
}

今回、Studentに設定するデータはJSONで定義する。 JSON -> Java Objectの変換は省略。

[{"id":1,"name":"Josy","age":32},
{"id":2,"name":"Remus","age":31},
{"id":3,"name":"Gavan","age":29},
{"id":4,"name":"Torrey","age":34},
{"id":5,"name":"Cass","age":35},
{"id":6,"name":"Hollis","age":23},
{"id":7,"name":"Gustav","age":29},
{"id":8,"name":"Trey","age":27},
{"id":9,"name":"Travis","age":27},
{"id":10,"name":"Lyndsie","age":34},
{"id":11,"name":"Erroll","age":32},
{"id":12,"name":"Martguerita","age":31},
{"id":13,"name":"Gisella","age":34},
{"id":14,"name":"Lenora","age":26},
{"id":15,"name":"Killian","age":23},
{"id":16,"name":"Samara","age":28},
{"id":17,"name":"Jo ann","age":20},
{"id":18,"name":"Betteann","age":32},
{"id":19,"name":"Catlaina","age":32},
{"id":20,"name":"Giovanna","age":30},
{"id":21,"name":"Sandy","age":22},
{"id":22,"name":"Del","age":29},
{"id":23,"name":"Bern","age":21},
{"id":24,"name":"Astrix","age":21},
{"id":25,"name":"Maible","age":26},
{"id":26,"name":"Marie-jeanne","age":34},
{"id":27,"name":"Anton","age":29},
{"id":28,"name":"Beryl","age":22},
{"id":29,"name":"Holli","age":23},
{"id":30,"name":"Timmy","age":30},
{"id":31,"name":"Dannie","age":26},
{"id":32,"name":"Berky","age":35},
{"id":33,"name":"Estell","age":24},
{"id":34,"name":"Orsola","age":29},
{"id":35,"name":"Ulysses","age":27},
{"id":36,"name":"Aldin","age":23},
{"id":37,"name":"Joan","age":25},
{"id":38,"name":"Nata","age":33},
{"id":39,"name":"Chrissy","age":23},
{"id":40,"name":"Giordano","age":28},
{"id":41,"name":"Michale","age":32},
{"id":42,"name":"Joell","age":31},
{"id":43,"name":"Hurleigh","age":31},
{"id":44,"name":"Cam","age":22},
{"id":45,"name":"Luise","age":25},
{"id":46,"name":"Saxe","age":28},
{"id":47,"name":"Irena","age":25},
{"id":48,"name":"Tarrah","age":34},
{"id":49,"name":"Claribel","age":21},
{"id":50,"name":"Myles","age":27}]

nameの昇順でソート

List<Student> students = // JSON -> Object変換

List<Student> byName = students
                .stream()
                .sorted(Comparator.comparing(Student::getName))
                .collect(Collectors.toList());
Student(id=36, name=Aldin, age=23)
Student(id=27, name=Anton, age=29)
Student(id=24, name=Astrix, age=21)
Student(id=32, name=Berky, age=35)
Student(id=23, name=Bern, age=21)
Student(id=28, name=Beryl, age=22)
Student(id=18, name=Betteann, age=32)
Student(id=44, name=Cam, age=22)
Student(id=5, name=Cass, age=35)
Student(id=19, name=Catlaina, age=32)
Student(id=39, name=Chrissy, age=23)
Student(id=49, name=Claribel, age=21)
...
省略
...
Student(id=9, name=Travis, age=27)
Student(id=8, name=Trey, age=27)
Student(id=35, name=Ulysses, age=27)

nameの降順でソート

reversed() を利用する。

List<Student> byName = students
                .stream()
                .sorted(Comparator.comparing(Student::getName).reversed())
                .collect(Collectors.toList());
Student(id=35, name=Ulysses, age=27)
Student(id=8, name=Trey, age=27)
Student(id=9, name=Travis, age=27)
Student(id=4, name=Torrey, age=34)
Student(id=30, name=Timmy, age=30)
Student(id=48, name=Tarrah, age=34)
...
省略
...
Student(id=44, name=Cam, age=22)
Student(id=18, name=Betteann, age=32)
Student(id=28, name=Beryl, age=22)
Student(id=23, name=Bern, age=21)
Student(id=32, name=Berky, age=35)
Student(id=24, name=Astrix, age=21)
Student(id=27, name=Anton, age=29)
Student(id=36, name=Aldin, age=23)

ageの降順、nameの昇順でソート

List<Student> byAgeAndName = students
                .stream()
                .sorted(Comparator.comparing(Student::getAge).reversed().thenComparing(Student::getName))
                .collect(Collectors.toList());
Student(id=32, name=Berky, age=35)
Student(id=5, name=Cass, age=35)
Student(id=13, name=Gisella, age=34)
Student(id=10, name=Lyndsie, age=34)
Student(id=26, name=Marie-jeanne, age=34)
Student(id=48, name=Tarrah, age=34)
Student(id=4, name=Torrey, age=34)
Student(id=38, name=Nata, age=33)
...
省略
...
Student(id=36, name=Aldin, age=23)
Student(id=39, name=Chrissy, age=23)
Student(id=29, name=Holli, age=23)
Student(id=6, name=Hollis, age=23)
Student(id=15, name=Killian, age=23)
Student(id=28, name=Beryl, age=22)
Student(id=44, name=Cam, age=22)
Student(id=21, name=Sandy, age=22)
Student(id=24, name=Astrix, age=21)
Student(id=23, name=Bern, age=21)
Student(id=49, name=Claribel, age=21)
Student(id=17, name=Jo ann, age=20)

Stream#collectを使用してJavaBeanリストから特定のフィールドのみを取得してリスト化する

public class Hoge {
    private String foo;
    private String bar;
    // constructor/getter/setter
}

Stream#collectを使用してHoge#barのリストを作成する。

// Hogeリストを作成
List<Hoge> hoges = Arrays.asList(new Hoge("f001", "b001")
                               , new Hoge("f002", "b002")
                               , new Hoge("f003", "b003"));
// Hoge#barのリストを作成
List<String> bars = hoges.stream().collect(ArrayList::new
                                        , (l, h) -> l.add(h.getBar())
                                        , (l1, l2) -> l1.addAll(l2));

System.out.println(bars); // [b001, b002, b003]

mapの場合

hoges.stream().map(Hoge::getBar).collect(Collectors.toList());

Spring Test DBUnitでJSONカラムにデータを投入する

Spring Test DBUnit@DatabaseSetup を使用してテストデータを投入する際に、対象のテーブルにJSONカラムが存在すると失敗するが、PostgresqlDataTypeFactoryを拡張することで投入できるようになる。

環境

  • Spring Boot 1.4.1
    • Spring Boot Test Starter
  • Spring Test DBUnit 1.3.0
  • PostgreSQL 9.5

PostgresqlDataTypeFactoryの拡張

DBUnitのFeature RequestsにJSONカラムに対応するための以下の2つのクラスが置いてある。※ステータスがpendingであることに注意
https://sourceforge.net/p/dbunit/feature-requests/188/

  • JsonType.java
  • PostgresqlDataTypeFactory.java

JSONBに対応していないので、PostgresqlDataTypeFactory.javaの一部を修正する。

public DataType createDataType(int sqlType, String sqlTypeName) throws DataTypeException {
    // 省略
    if ("json".equals(sqlTypeName) || 
        "jsonb".equals(sqlTypeName) /* ←を追加*/ ) {
            return new JsonType()
    }
    // 省略
}

Configurationクラスの修正

上の2つのクラスを適当なパッケージに配置後、Configurationクラスの修正を行う。

@Configuration
public class TestConfig {
    @Bean
    public DataSource dataSource() {
        // 省略
    }

    @Bean
    public DatabaseConfigBean dbUnitDatabaseConfig() {
        DatabaseConfigBean dbConfig = new DatabaseConfigBean();
        dbConfig.setDatatypeFactory(new PostgresqlDataTypeFactory());
        return dbConfig;
    }

    @Bean
    public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnection() {
        DatabaseDataSourceConnectionFactoryBean dbConnection = new DatabaseDataSourceConnectionFactoryBean(dataSource());
        dbConnection.setDatabaseConfig(dbUnitDatabaseConfig());
        return dbConnection;
    }
}

これでJSONデータの投入が可能となる。