Powered by Google App Engine

Google guava-libraries

 

Ordering

Orderingはjavaの最強のソートライブラリではないでしょうか。Collections.sort()と違い、NullPointerExceptionを起こさなくする事もできます。今回はOrderingを使ってDTOのリストを自由自在にソートしてみましょう。

新サイト、tree-mapsを公開しました!!

tree-maps: 地図のWEB TOOLの事ならtree-mapsにお任せ!

地図に関するWEB TOOL専門サイトです!!

大画面で大量の緯度経度を一気にプロット、ジオコーディング、DMS<->DEGの相互変換等ができます!

◯ 広告
public class StrDto {
    public String col1;
    public String col2;
    public StrDto(String col1, String col2) {
        this.col1 = col1;
        this.col2 = col2;
    }
}
import java.util.List;

import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;

public class OrderingTest {

    public static void main(String[] args) {
        OrderingTest self = new OrderingTest();
        self.sortStr();
    }

    public void sortStr() {
        List<StrDto> dtos = Lists.newArrayList();
        dtos.add(new StrDto("10", "2"));
        dtos.add(new StrDto("10", "1"));
        dtos.add(new StrDto("11", "2"));
        dtos.add(new StrDto("11", "1"));
        dtos.add(new StrDto("100", "2"));
        dtos.add(new StrDto("100", "1"));
        dtos.add(new StrDto("110", "2"));
        dtos.add(new StrDto("110", "1"));

        ImmutableList<StrDto> sorted = new Ordering<StrDto>() {
            public int compare(StrDto o1, StrDto o2) {
                return ComparisonChain.start()
                    // 第1ソート:col1の昇順
                    .compare(o1.col1, o2.col1, Ordering.natural().nullsLast())
                    // 第2ソート:col2の降順
                    .compare(o2.col2, o1.col2, Ordering.natural().nullsLast())
                    .result();
            }
        }.immutableSortedCopy(dtos);
        for (StrDto dto : sorted)
            System.out.println(dto.col1 + "," + dto.col2);
    }
}

---実行結果---
10,1
10,2
100,1
100,2
11,1
11,2
110,1
110,2

o1,o2という順番に書くと昇順に、o2,o1と書くと降順になります。

ソートする項目はcol1,col2等で指定します。順番を任意に変更可能です。

nullsLast()はnull値を末尾に配置しNullPointerExceptionが起きなくなる優れものです。

public class IntDto {
    public int col1;
    public int col2;
    public IntDto(int col1, int col2) {
        this.col1 = col1;
        this.col2 = col2;
    }
}
import java.util.List;

import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;

public class OrderingTest {

    public static void main(String[] args) {
        OrderingTest self = new OrderingTest();
        self.sortInt();
    }

    public void sortInt() {
        List<IntDto> dtos = Lists.newArrayList();
        dtos.add(new IntDto(1, 100));
        dtos.add(new IntDto(3, 100));
        dtos.add(new IntDto(2, 103));
        dtos.add(new IntDto(4, 103));
        dtos.add(new IntDto(6, 102));
        dtos.add(new IntDto(5, 102));

        ImmutableList<IntDto> sorted = new Ordering<IntDto>() {
            public int compare(IntDto o1, IntDto o2) {
                return ComparisonChain.start()
                    // 第1ソート:col2:降順
                    .compare(o2.col2, o1.col2, Ordering.natural().nullsLast())
                    // 第2ソート:col1:昇順
                    .compare(o1.col1, o2.col1, Ordering.natural().nullsLast())
                    .result();
            }
        }.immutableSortedCopy(dtos);
        for (IntDto dto : sorted) {
            System.out.println(dto.col1 + "," + dto.col2);
        }
    }
}

---実行結果---
2,103
4,103
5,102
6,102
1,100
3,100

col2を第1ソートで降順にしてみました。

数値型なので綺麗に並びましたね。

public class DoubleDto {
    public Double col1;
    public Double col2;
    public DoubleDto(Double col1, Double col2) {
        this.col1 = col1;
        this.col2 = col2;
    }
}
import java.util.List;

import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;

public class OrderingTest {

	public static void main(String[] args) {
		OrderingTest self = new OrderingTest();
		self.sortDouble();
	}

	public void sortDouble() {
		List<DoubleDto> dtos = Lists.newArrayList();
		dtos.add(new DoubleDto(1.0D, 100.0D));
		dtos.add(new DoubleDto(1.01D, 100.0D));
		dtos.add(new DoubleDto(1.011D, 101.0D));
		dtos.add(new DoubleDto(null, 101.0D));
		dtos.add(new DoubleDto(1.011D, null));
		dtos.add(new DoubleDto(1.012D, null));

		ImmutableList<DoubleDto> sorted = new Ordering<DoubleDto>() {

			public int compare(DoubleDto o1, DoubleDto o2) {
				return ComparisonChain.start()
                    // 第1ソート:col1:昇順(nullを末尾に)
				    .compare(o1.col1, o2.col1, Ordering.natural().nullsLast())
                    // 第2ソート:col1:昇順(nullを先頭に)
					.compare(o1.col2, o2.col2, Ordering.natural().nullsFirst())
					.result();
			}
		}.immutableSortedCopy(dtos);
		for (DoubleDto dto : sorted) {
			System.out.println(dto.col1 + "," + dto.col2);
		}
	}
}

---実行結果---
1.0,   100.0
1.01,  100.0
1.011, null
1.011, 101.0
1.012, null
null,  101.0

nullを挟んでみました。勿論NullPointerExceptionは起きません。

nullsLast()で末尾に、nullsFirst()で先頭にnullが配置されましたね。

小数点もきちんと考慮されてソートされています。

public class DateDto {
    public Date col1;
    public Date col2;
    public DateDto(Date col1, Date col2) {
        this.col1 = col1;
        this.col2 = col2;
    }
}
import java.util.List;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;

public class OrderingTest {

    public static void main(String[] args) {
        OrderingTest self = new OrderingTest();
        self.sortDate();
    }

    public void sortDate() {
        final String DF = "yyyy/MM/dd HH:mm:ss";
        List<DateDto> dtos = Lists.newArrayList();
        dtos.add(new DateDto(DateTimeFormat.forPattern(DF).parseDateTime("2014/10/01 00:00:00").toDate(),
                DateTimeFormat.forPattern(DF).parseDateTime("2014/10/01 00:00:00").toDate()));
        dtos.add(new DateDto(DateTimeFormat.forPattern(DF).parseDateTime("2014/10/01 00:00:00").toDate(),
                DateTimeFormat.forPattern(DF).parseDateTime("2014/10/01 00:00:01").toDate()));
        dtos.add(new DateDto(DateTimeFormat.forPattern(DF).parseDateTime("2014/10/10 00:00:00").toDate(),
                DateTimeFormat.forPattern(DF).parseDateTime("2014/10/01 00:00:10").toDate()));
        dtos.add(new DateDto(DateTimeFormat.forPattern(DF).parseDateTime("2014/10/10 00:00:00").toDate(),
                DateTimeFormat.forPattern(DF).parseDateTime("2014/10/01 00:00:11").toDate()));

        ImmutableList<DateDto> sorted = new Ordering<DateDto>() {

            public int compare(DateDto o1, DateDto o2) {
                return ComparisonChain.start()
                    // 第1ソート:col1:降順
                    .compare(o2.col1, o1.col1, Ordering.natural().nullsLast())
                    // 第2ソート:col2:降順
                    .compare(o2.col2, o1.col2, Ordering.natural().nullsLast())
                    .result();
            }
        }.immutableSortedCopy(dtos);
        for (DateDto dto : sorted) {
            System.out.println(new DateTime(dto.col1).toString(DF) + "," + new DateTime(dto.col2).toString(DF));
        }
    }
}

---実行結果---
2014/10/10 00:00:00,2014/10/01 00:00:11
2014/10/10 00:00:00,2014/10/01 00:00:10
2014/10/01 00:00:00,2014/10/01 00:00:01
2014/10/01 00:00:00,2014/10/01 00:00:00

日付もきちんとソートできてますね。中々凄いです。

DateTimeはjoda-timeのクラスで、日付を簡単に便利扱えるライブラリです。

◯ 広告