リスト重複排除 + Java8-Stream ストリーム操作 リスト重複排除および指定フィールド重複排除
新しいリスト配列を作成します。
List list = new ArrayList();
list.add(26);
list.add(39);
list.add(39);
list.add(39);
list.add(39);
list.add(5);
list.add(40);
list.add(39);
list.add(25);
System.out.println(list);
方法 1: 新しい Java8 機能ストリームを使用してリストの重複を除去する [一般的に使用される]
注: オブジェクトを重複排除する場合、単一の重複排除ではなく、同じオブジェクト内のすべてのフィールドのみを重複排除できます。
List newList = list.stream().distinct().collect(Collectors.toList());
System.out.println(“java8新特性stream去重:”+newList);
list.add(39);
方法 3: 順序を乱すことなく、セットを判断して重複排除するように設定する
protected final <T> List<T> removeDuplicates(List<T> list) {
return new ArrayList<>(new LinkedHashSet<>(list))
}
Java8-Stream ストリーム操作 リスト重複排除および指定フィールドの重複排除
方法 1: Java8-Stream ストリーム操作 リストの重複排除と指定されたフィールドの重複排除
stream の個別の重複排除メソッドは、Object.equals と Object.hashCode の 2 つのメソッドに基づいて、重複しているかどうかを判断します。
したがって、この機能を使用して、pojo の Object.equals と Object.hashCode の 2 つのメソッドを書き換えることで実現できます。
1. BookクラスのequalsメソッドとhashCodeメソッドを書き換え、名前を使用して比較が同じかどうかを判断し、ストリームのdistinctメソッドを使用して重複を排除します。
class Book {
...
@Override
public String toString() {
return String.format("(%s,%s,%s)", id, name, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(name, book.name);
}
}
List<Book> distinctNameBooks1 = books.stream().distinct().collect(Collectors.toList());
System.out.println(distinctNameBooks1);
概要:equals メソッドと hashCode メソッドを書き換えて実際のニーズに応じて比較することにより、ストリームの個別のメソッドを直接使用して重複を排除でき、より便利です。オブジェクト クラスが不便であるか、変更できない場合があります。実装されているか、参照されているサードパーティ パッケージは変更できないため、この方法ではフィールドごとに柔軟に重複排除を行うことができません。
2. Collectors.collectingAndThen の Collectors.toCollection を通じて、TreeSet を使用してコンストラクター内のフィールドを指定します
フィールドの重複排除
List<ProjectInfoVo> vo = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ProjectInfoVo.class));
ArrayList<ProjectInfoVo> collect = vo.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(p -> p.getProjectId()))), ArrayList::new));
複数フィールドの重複排除
List<ProjectInfoVo> vo = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ProjectInfoVo.class));
ArrayList<ProjectInfoVo> collect = vo.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(p -> p.getProjectId()+";"+p.getMember()))), ArrayList::new));
概要:
stream が提供するメソッドを使用すると、コードは非常に簡潔になりますが、欠点は、重複排除効果は得られますが、リスト内の順序が変更され、一部のシーンでは順序を維持する必要があることです。
3. カスタム メソッド Comparator.comparing(p -> p.get***())
カスタム メソッド クラス - DifferentByKey
public class StreamUtils {
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
}
単一フィールド
List<ProjectInfoVo> acceptances = vo.stream()
.filter(StreamUtils.distinctByKey(b -> b.getProjectId()))
.collect(Collectors.toList());
複数のフィールド
List<ProjectInfoVo> acceptances = vo.stream()
.filter(StreamUtils.distinctByKey(b -> b.getProjectId()))
.filter(StreamUtils.distinctByKey(b -> b.getMember()))
.collect(Collectors.toList());
概要: 重複排除メソッドをカプセル化して定義し、フィルター メソッドと組み合わせることで、フィールドごとに柔軟に重複排除を行い、元のリストの順序を維持できます。欠点は、HashMap が内部で定義されているため、ある程度のメモリを占有することです。追加のメソッド定義があります。
4. ストリームのフィルター メソッドを使用して重複排除を行い、重複排除メソッドを定義せず、外部で HashMap を作成します。
Map<Object, Boolean> map = new HashMap<>();
List<Book> distinctNameBooks4 = books.stream().filter(i -> map.putIfAbsent(i.getName(), Boolean.TRUE) == null).collect(Collectors.toList());
System.out.println(distinctNameBooks4);
概要: フィルター方式と連携して重複排除を実現しますが、別途の作成方式はなく、元のリストの順序を維持するために一時的に HashMap を定義しますが、ある程度のメモリを消費するのが欠点です。