Работая в Java 8, у меня есть такое TreeSet
определение:
private TreeSet<PositionReport> positionReports =
new TreeSet<>(Comparator.comparingLong(PositionReport::getTimestamp));
PositionReport
это довольно простой класс, определенный следующим образом:
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;
}
}
Это прекрасно работает.
Теперь я хочу удалить записи из того, TreeSet positionReports
где timestamp
старше некоторого значения. Но я не могу найти правильный синтаксис Java 8, чтобы выразить это.
Эта попытка действительно компилируется, но дает мне новый TreeSet
с неопределенным компаратором:
positionReports = positionReports
.stream()
.filter(p -> p.timestamp >= oldestKept)
.collect(Collectors.toCollection(TreeSet::new))
Как я могу выразить, что хочу собрать в TreeSet
компаратор лайк Comparator.comparingLong(PositionReport::getTimestamp)
?
Я бы подумал что-то вроде
positionReports = positionReports
.stream()
.filter(p -> p.timestamp >= oldestKept)
.collect(
Collectors.toCollection(
TreeSet::TreeSet(Comparator.comparingLong(PositionReport::getTimestamp))
)
);
Но это не компилируется / не выглядит допустимым синтаксисом для ссылок на методы.
источник
.collect(Collectors.toCollection(TreeSet::new));
toCollection in class Collectors cannot be applied to given types
Collectors::toCollection
: a,Supplier
который возвращает aCollection
.Supplier
- это тип с одним абстрактным методом, что означает, что он может быть целью лямбда-выражения, как в этом ответе. Лямбда-выражение не должно принимать аргументов (следовательно, пустой список аргументов()
) и возвращать коллекцию с типом элемента, который соответствует типу элементов в собираемом вами потоке (в данном случае aTreeSet<PositionReport>
).Это легко, просто используйте следующий код:
positionReports = positionReports .stream() .filter(p -> p.timestamp >= oldestKept) .collect( Collectors.toCollection(()->new TreeSet<>(Comparator.comparingLong(PositionReport::getTimestamp) )));
источник
Вы можете просто преобразовать в SortedSet в конце (при условии, что вы не возражаете против дополнительной копии).
positionReports = positionReports .stream() .filter(p -> p.getTimeStamp() >= oldestKept) .collect(Collectors.toSet()); return new TreeSet(positionReports);
источник
compareTo()
как 0, а другой может не иметь для некоторых сравнений. Все те, гдеcompareTo()
0 потеряно, так как это набор.)Существует метод по сбору для этого без использования потоков:
default boolean removeIf(Predicate<? super E> filter)
. См. Javadoc .Итак, ваш код может выглядеть так:
источник
Проблема с TreeSet заключается в том, что компаратор, который нам нужен для сортировки элементов, также используется для обнаружения дубликатов при вставке элементов в набор. Поэтому, если функция компаратора равна 0 для двух элементов, он ошибочно отбрасывает один, считая его дубликатом.
Обнаружение дубликатов должно выполняться отдельным правильным методом hashCode элементов. Я предпочитаю использовать простой HashSet для предотвращения дублирования с помощью hashCode с учетом всех свойств (id и name в примере) и возвращать простой отсортированный список при получении элементов (сортировка только по имени в примере):
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()); } }
источник
positionReports = positionReports.stream() .filter(p -> p.getTimeStamp() >= oldestKept) .collect(Collectors.toCollection(() -> new TreeSet<PositionReport>(Comparator.comparingLong(PositionReport::getTimestamp))));
источник