Java把 List
中重複的元素移除的方法如下。
把 List
物件做為 HashSet
建構式的參數取得 HashSet
物件即可得到不重複元素的集合,因為 SET
的特性是所含的元素必須是唯一的。
List<Integer> integerList = Arrays.asList(1, 2, 2, 3, 3, 4, 4, 4, 5);
Set<Integer> integerSet = new HashSet<>(integerList);
System.out.println(integerSet); // [1, 2, 3, 4, 5]
或是轉為 Stream
用 distinct()
排除多的重覆。
List<Integer> integerList = Arrays.asList(1, 2, 2, 3, 3, 4, 4, 4, 5);
integerList = integerList.stream().distinct().collect(Collectors.toList());
System.out.println(integerList); // [1, 2, 3, 4, 5]
若 List
的元素為自訂類別的物件則該類別必須覆寫 equals()
與 hashCode()
才有效果。
例如下面的 Order
依照 id
來區別是否相同,所以複寫 equals()
及 hashCode()
時僅利用 id
比較及計算。
Order
package com.abc.demo;
import java.util.Objects;
public class Order {
private long id; // key
private long amount;
Order(long id, long amount) {
this.id = id;
this.amount = amount;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Order order = (Order) o;
return id == order.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return String.format("id=%s, amount=%s", id, amount);
}
}
下面建立有重覆 Order
的 List<Order>
,利用 HashSet
排除重覆的物件。
List<Order> orderList = Arrays.asList(
new Order(1, 10),
new Order(2, 100),
new Order(2, 100), // duplicate
new Order(3, 1000),
new Order(3, 1000) // duplicate
);
Set<Order> orderSet = new HashSet<>(orderList);
System.out.println(orderSet); // [id=1, amount=10, id=2, amount=100, id=3, amount=1000]
利用 Stream.distinct()
排除重覆的物件。
List<Order> orderList = Arrays.asList(
new Order(1, 10),
new Order(2, 100),
new Order(2, 100), // duplicate
new Order(3, 1000),
new Order(3, 1000) // duplicate
);
orderList = orderList.stream().distinct().collect(Collectors.toList());
System.out.println(orderList); // [id=1, amount=10, id=2, amount=100, id=3, amount=1000]
若要依物件的多個非 equals()
及 hashCode()
的屬性來排除重覆,可利用 TreeSet
,其為有排序的 Set
可定義排序的規則。
例如下面的 OrderPayment
的 equals()
及 hashCode()
僅依 id
來區別是否相同。
OrderPayment
package com.abc.demo;
import java.util.Objects;
public class OrderPayment {
private long id;
private String orderId;
private String paymentId;
public OrderPayment(long id, String orderId, String paymentId) {
this.id = id;
this.orderId = orderId;
this.paymentId = paymentId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OrderPayment that = (OrderPayment) o;
return id == that.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "OrderPayment{" +
"id=" + id +
", orderId='" + orderId + '\'' +
", paymentId='" + paymentId + '\'' +
'}';
}
// getters and setters
}
但下面的 List<OrderPayment>
要根據 orderId
及 paymentId
是否相同來排除重覆的元素,則在建構 TreeSet
時傳入依 orderId
結合 paymentId
的 Comparator
來比較。
List<OrderPayment> orderPaymentList = Arrays.asList(
new OrderPayment(1, "H001", "C001"),
new OrderPayment(1, "H001", "C001"), // duplicate
new OrderPayment(2, "H001", "C002"),
new OrderPayment(3, "H002", "C003"),
new OrderPayment(3, "H002", "C003") // duplicate
);
Set<OrderPayment> set = new TreeSet<>(
Comparator.comparing(orderPayment ->
orderPayment.getOrderId() + orderPayment.getPaymentId()));
set.addAll(orderPaymentList);
orderPaymentList = new ArrayList<>(set);
System.out.println(orderPaymentList); // [OrderPayment{id=1, orderId='H001', paymentId='C001'}, OrderPayment{id=2, orderId='H001', paymentId='C002'}, OrderPayment{id=3, orderId='H002', paymentId='C003'}]
或用 Stream.collect()
搭配 TreeSet
排除多餘的重覆。
List<OrderPayment> orderPaymentList = Arrays.asList(
new OrderPayment(1, "H001", "C001"),
new OrderPayment(1, "H001", "C001"), // duplicate
new OrderPayment(2, "H001", "C002"),
new OrderPayment(3, "H002", "C003"),
new OrderPayment(3, "H002", "C003") // duplicate
);
orderPaymentList = orderPaymentList.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(orderPayment ->
orderPayment.getOrderId() + orderPayment.getPaymentId()
))), ArrayList::new));
System.out.println(orderPaymentList); // [OrderPayment{id=1, orderId='H001', paymentId='C001'}, OrderPayment{id=2, orderId='H001', paymentId='C002'}, OrderPayment{id=3, orderId='H002', paymentId='C003'}]