Java Comparable Interface - Java 147

Java Comparable Interface – Java 147

Java Comparable Interface

常用於集合或陣列比較元素,提供了單一的排序序列,此外還介紹 Apache Commons Lang 、 Guava 其他程式庫等實作方式, Comparable Interface 介紹 compareTo 等方法進行操作,了解 Comparable 的不同操作和方法,本篇增加了範例,並透過單元測試來驗證產出結果。

大於 o 傳回 1 。
等於 o 傳回 0 。
小於 o 傳回 -1 。

public interface Comparable<T> {
    public int compareTo(T o);
}    

檔案目錄

./
   +- src
       +- test
       |   +- org
       |       +- ruoxue
       |           +- java_147
       |               +- comparable
       |                   +- ComparableInterfaceTest.java   

單元測試

Comparable Interface Java 提供 compareTo 、 Apache Commons Lang 、 Guava 等方法操作 Comparable Interface 。

compareTo

Comparable Interface Java 建立集合及陣列,比對字串或數字,由小到大排序。

	@NoArgsConstructor
	@Getter
	@Setter
	@Builder
	public static class Fruit implements Comparable<Fruit> {
		private String name;
		private double quantity;
		private int type;

		public Fruit(String name, double quantity, int type) {
			this.name = name;
			this.quantity = quantity;
			this.type = type;
		}

		public String toString() {
			ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
			builder.appendSuper(super.toString());
			builder.append("name", name);
			builder.append("quantity", quantity);
			builder.append("type", type);
			return builder.toString();
		}

		@Override
		public int compareTo(Fruit o) {
			int ret = this.name.compareTo(o.name);
			if (ret == 0)
				ret = Double.compare(this.quantity, o.quantity);
			return ret;
		}
	}

	@Test
	public void compareTo() {
		List<Fruit> list = Arrays.asList(new Fruit("Mango", Double.MAX_VALUE, 1), new Fruit("Mango", -1, 3),
				new Fruit("Peach", 3, 1), new Fruit("Orange", 2, 1));
		System.out.println(list);

		Collections.sort(list);
		System.out.println(list);
		assertEquals(-1d, list.get(0).getQuantity(), 2);
		assertEquals(Double.MAX_VALUE, list.get(1).getQuantity(), 2);
	}
	
[{"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Mango","quantity":-1.0,"type":3}, {"name":"Peach","quantity":3.0,"type":1}, {"name":"Orange","quantity":2.0,"type":1}]
[{"name":"Mango","quantity":-1.0,"type":3}, {"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Orange","quantity":2.0,"type":1}, {"name":"Peach","quantity":3.0,"type":1}]

ComparisonChain_compare

Comparable Interface in Java 建立集合及陣列,使用 ComparisonChain ,比對字串或數字,由大到小排序。

	@NoArgsConstructor
	@Getter
	@Setter
	@Builder
	public static class GuavaFruit implements Comparable<GuavaFruit> {
		private String name;
		private double quantity;
		private int type;

		public GuavaFruit(String name, double quantity, int type) {
			this.name = name;
			this.quantity = quantity;
			this.type = type;
		}

		public String toString() {
			ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
			builder.appendSuper(super.toString());
			builder.append("name", name);
			builder.append("quantity", quantity);
			builder.append("type", type);
			return builder.toString();
		}

		@Override
		public int compareTo(GuavaFruit o) {
			return ComparisonChain.start().compare(this.name, o.name).compare(this.quantity, o.quantity).result();
		}
	}

	@Test
	public void ComparisonChain_compare() {
		List<GuavaFruit> list = Arrays.asList(new GuavaFruit("Mango", Double.MAX_VALUE, 1),
				new GuavaFruit("Mango", -1, 3), new GuavaFruit("Peach", 3, 1), new GuavaFruit("Orange", 2, 1));
		System.out.println(list);

		Collections.sort(list);
		System.out.println(list);
		assertEquals(-1d, list.get(0).getQuantity(), 2);
		assertEquals(Double.MAX_VALUE, list.get(1).getQuantity(), 2);
	}
[{"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Mango","quantity":-1.0,"type":3}, {"name":"Peach","quantity":3.0,"type":1}, {"name":"Orange","quantity":2.0,"type":1}]
[{"name":"Mango","quantity":-1.0,"type":3}, {"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Orange","quantity":2.0,"type":1}, {"name":"Peach","quantity":3.0,"type":1}]

CompareToBuilder_toComparison

Comparable Interface in Java 建立集合及陣列,使用 CompareToBuilder ,比對字串或數字,由大到小排序。

	@NoArgsConstructor
	@Getter
	@Setter
	@Builder
	public static class ApacheFruit implements Comparable<ApacheFruit> {
		private String name;
		private double quantity;
		private int type;

		public ApacheFruit(String name, double quantity, int type) {
			this.name = name;
			this.quantity = quantity;
			this.type = type;
		}

		public String toString() {
			ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
			builder.appendSuper(super.toString());
			builder.append("name", name);
			builder.append("quantity", quantity);
			builder.append("type", type);
			return builder.toString();
		}

		@Override
		public int compareTo(ApacheFruit o) {
			return new CompareToBuilder().append(this.name, o.name).append(this.quantity, o.quantity).toComparison();
		}
	}

	@Test
	public void CompareToBuilder_toComparison() {
		List<ApacheFruit> list = Arrays.asList(new ApacheFruit("Mango", Double.MAX_VALUE, 1),
				new ApacheFruit("Mango", -1, 3), new ApacheFruit("Peach", 3, 1), new ApacheFruit("Orange", 2, 1));
		System.out.println(list);

		Collections.sort(list);
		System.out.println(list);
		assertEquals(-1d, list.get(0).getQuantity(), 2);
		assertEquals(Double.MAX_VALUE, list.get(1).getQuantity(), 2);
	}
[{"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Mango","quantity":-1.0,"type":3}, {"name":"Peach","quantity":3.0,"type":1}, {"name":"Orange","quantity":2.0,"type":1}]
[{"name":"Mango","quantity":-1.0,"type":3}, {"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Orange","quantity":2.0,"type":1}, {"name":"Peach","quantity":3.0,"type":1}]

ComparableInterfaceTest.java

Comparable Interface in Java 新增單元測試,驗證 Java Comparable Interface Example 是否符合預期。

package org.ruoxue.java_147.comparable;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang3.builder.CompareToBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.junit.Test;

import com.google.common.collect.ComparisonChain;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

public class ComparableInterfaceTest {

	@NoArgsConstructor
	@Getter
	@Setter
	@Builder
	public static class Fruit implements Comparable<Fruit> {
		private String name;
		private double quantity;
		private int type;

		public Fruit(String name, double quantity, int type) {
			this.name = name;
			this.quantity = quantity;
			this.type = type;
		}

		public String toString() {
			ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
			builder.appendSuper(super.toString());
			builder.append("name", name);
			builder.append("quantity", quantity);
			builder.append("type", type);
			return builder.toString();
		}

		@Override
		public int compareTo(Fruit o) {
			int ret = this.name.compareTo(o.name);
			if (ret == 0)
				ret = Double.compare(this.quantity, o.quantity);
			return ret;
		}
	}

	@Test
	public void compareTo() {
		List<Fruit> list = Arrays.asList(new Fruit("Mango", Double.MAX_VALUE, 1), new Fruit("Mango", -1, 3),
				new Fruit("Peach", 3, 1), new Fruit("Orange", 2, 1));
		System.out.println(list);

		Collections.sort(list);
		System.out.println(list);
		assertEquals(-1d, list.get(0).getQuantity(), 2);
		assertEquals(Double.MAX_VALUE, list.get(1).getQuantity(), 2);
	}

	@NoArgsConstructor
	@Getter
	@Setter
	@Builder
	public static class GuavaFruit implements Comparable<GuavaFruit> {
		private String name;
		private double quantity;
		private int type;

		public GuavaFruit(String name, double quantity, int type) {
			this.name = name;
			this.quantity = quantity;
			this.type = type;
		}

		public String toString() {
			ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
			builder.appendSuper(super.toString());
			builder.append("name", name);
			builder.append("quantity", quantity);
			builder.append("type", type);
			return builder.toString();
		}

		@Override
		public int compareTo(GuavaFruit o) {
			return ComparisonChain.start().compare(this.name, o.name).compare(this.quantity, o.quantity).result();
		}
	}

	@Test
	public void ComparisonChain_compare() {
		List<GuavaFruit> list = Arrays.asList(new GuavaFruit("Mango", Double.MAX_VALUE, 1),
				new GuavaFruit("Mango", -1, 3), new GuavaFruit("Peach", 3, 1), new GuavaFruit("Orange", 2, 1));
		System.out.println(list);

		Collections.sort(list);
		System.out.println(list);
		assertEquals(-1d, list.get(0).getQuantity(), 2);
		assertEquals(Double.MAX_VALUE, list.get(1).getQuantity(), 2);
	}

	@NoArgsConstructor
	@Getter
	@Setter
	@Builder
	public static class ApacheFruit implements Comparable<ApacheFruit> {
		private String name;
		private double quantity;
		private int type;

		public ApacheFruit(String name, double quantity, int type) {
			this.name = name;
			this.quantity = quantity;
			this.type = type;
		}

		public String toString() {
			ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
			builder.appendSuper(super.toString());
			builder.append("name", name);
			builder.append("quantity", quantity);
			builder.append("type", type);
			return builder.toString();
		}

		@Override
		public int compareTo(ApacheFruit o) {
			return new CompareToBuilder().append(this.name, o.name).append(this.quantity, o.quantity).toComparison();
		}
	}

	@Test
	public void CompareToBuilder_toComparison() {
		List<ApacheFruit> list = Arrays.asList(new ApacheFruit("Mango", Double.MAX_VALUE, 1),
				new ApacheFruit("Mango", -1, 3), new ApacheFruit("Peach", 3, 1), new ApacheFruit("Orange", 2, 1));
		System.out.println(list);

		Collections.sort(list);
		System.out.println(list);
		assertEquals(-1d, list.get(0).getQuantity(), 2);
		assertEquals(Double.MAX_VALUE, list.get(1).getQuantity(), 2);
	}
}

心得分享

Java Comparable Interface Example 會影響原類別,即實際類別被修改,使用 Collections.sort(List) 方法對 Comparable 類型的元素進行排序, Comparable Interface in Java 提供了幾種 Comparable 常見方法的操作範例,熟悉這些方法的操作,能夠提高開發效率,節省維護上的成本。

發佈留言