Bekerja di Java 8, saya memiliki TreeSet
definisi seperti ini:
private TreeSet<PositionReport> positionReports =
new TreeSet<>(Comparator.comparingLong(PositionReport::getTimestamp));
PositionReport
adalah kelas yang agak sederhana yang didefinisikan seperti ini:
public static final class PositionReport implements Cloneable {
private final long timestamp;
private final Position position;
public static PositionReport create(long timestamp, Position position) {
return new PositionReport(timestamp, position);
}
private PositionReport(long timestamp, Position position) {
this.timestamp = timestamp;
this.position = position;
}
public long getTimestamp() {
return timestamp;
}
public Position getPosition() {
return position;
}
}
Ini bekerja dengan baik.
Sekarang saya ingin menghapus entri dari TreeSet positionReports
mana timestamp
yang lebih tua dari beberapa nilai. Tetapi saya tidak dapat menemukan sintaks Java 8 yang benar untuk mengungkapkan ini.
Upaya ini sebenarnya mengkompilasi, tetapi memberi saya yang baru TreeSet
dengan pembanding yang tidak ditentukan:
positionReports = positionReports
.stream()
.filter(p -> p.timestamp >= oldestKept)
.collect(Collectors.toCollection(TreeSet::new))
Bagaimana cara saya mengungkapkan, bahwa saya ingin mengumpulkan menjadi TreeSet
dengan pembanding seperti Comparator.comparingLong(PositionReport::getTimestamp)
?
Saya akan memikirkan sesuatu seperti
positionReports = positionReports
.stream()
.filter(p -> p.timestamp >= oldestKept)
.collect(
Collectors.toCollection(
TreeSet::TreeSet(Comparator.comparingLong(PositionReport::getTimestamp))
)
);
Tetapi ini tidak mengkompilasi / tampaknya sintaks yang valid untuk referensi metode.
sumber
.collect(Collectors.toCollection(TreeSet::new));
toCollection in class Collectors cannot be applied to given types
Collectors::toCollection
: aSupplier
yang mengembalikan aCollection
.Supplier
adalah tipe dengan hanya satu metode abstrak, yang berarti dapat menjadi target ekspresi lambda seperti dalam jawaban ini. Ekspresi lambda tidak boleh mengambil argumen (karena itu daftar argumen kosong()
) dan mengembalikan koleksi dengan tipe elemen yang cocok dengan tipe elemen dalam aliran yang Anda kumpulkan (dalam hal ini aTreeSet<PositionReport>
).Ini mudah, cukup gunakan kode berikutnya:
positionReports = positionReports .stream() .filter(p -> p.timestamp >= oldestKept) .collect( Collectors.toCollection(()->new TreeSet<>(Comparator.comparingLong(PositionReport::getTimestamp) )));
sumber
Anda bisa mengubahnya menjadi SortedSet di akhir (asalkan Anda tidak keberatan dengan salinan tambahan).
positionReports = positionReports .stream() .filter(p -> p.getTimeStamp() >= oldestKept) .collect(Collectors.toSet()); return new TreeSet(positionReports);
sumber
compareTo()
sebagai 0 sedangkan yang lain mungkin tidak untuk beberapa perbandingan. Semua yangcompareTo()
memiliki 0 hilang karena ini adalah satu set.)Ada metode pada Koleksi untuk ini tanpa harus menggunakan aliran:
default boolean removeIf(Predicate<? super E> filter)
. Lihat Javadoc .Jadi kode Anda bisa saja terlihat seperti ini:
sumber
Masalah dengan TreeSet adalah bahwa pembanding yang kita inginkan untuk menyortir item digunakan juga untuk mendeteksi duplikat saat memasukkan item ke dalam set. Jadi, jika fungsi pembanding adalah 0 untuk dua item, salah satu item akan dibuang karena dianggap sebagai duplikat.
Deteksi duplikat harus dilakukan dengan metode hashCode terpisah yang benar dari item tersebut. Saya lebih suka menggunakan HashSet sederhana untuk mencegah duplikat dengan hashCode mempertimbangkan semua properti (id dan nama dalam contoh) dan mengembalikan Daftar yang diurutkan sederhana saat mendapatkan item (hanya mengurutkan berdasarkan nama dalam contoh):
public class ProductAvailableFiltersDTO { private Set<FilterItem> category_ids = new HashSet<>(); public List<FilterItem> getCategory_ids() { return category_ids.stream() .sorted(Comparator.comparing(FilterItem::getName)) .collect(Collectors.toList()); } public void setCategory_ids(List<FilterItem> category_ids) { this.category_ids.clear(); if (CollectionUtils.isNotEmpty(category_ids)) { this.category_ids.addAll(category_ids); } } } public class FilterItem { private String id; private String name; public FilterItem(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof FilterItem)) return false; FilterItem that = (FilterItem) o; return Objects.equals(getId(), that.getId()) && Objects.equals(getName(), that.getName()); } @Override public int hashCode() { return Objects.hash(getId(), getName()); } }
sumber
positionReports = positionReports.stream() .filter(p -> p.getTimeStamp() >= oldestKept) .collect(Collectors.toCollection(() -> new TreeSet<PositionReport>(Comparator.comparingLong(PositionReport::getTimestamp))));
sumber