Может ли это вызвать проблемы со сборкой мусора?
-
09-09-2019 - |
Вопрос
Я написал немного Linq, например DSL, поверх Коллекции Google
public class IterableQuery {
public static <T> Where<T> from(Iterable<T> originalCollection) {
return new Where<T>( Iterables.transform(originalCollection, IterableQuery.<T>SAME()));
}
private static <T> Function<T, T> SAME() {
return new Function<T, T>(){
public T apply(T arg0) {
return arg0;
}
};
}
public static class SelectOrderBy<T>{
private final Iterable<T> iterable;
public SelectOrderBy(Iterable<T> iteable) {
this.iterable = iteable;
}
public SelectOrderBy<T> orderyBy( Comparator<T> sort ){
Ordering.forComparator(sort).sort((List< ? extends T>) iterable);
return new SelectOrderBy<T>( iterable);
}
public <F> Iterable<F> select( Function<? super T,? extends F> function){
return Iterables.transform(iterable, function);
}
public Iterable<T> selectEveryThing( ){
return iterable;
}
}
public static class Where<T>{
private final Iterable<T> iterable;
public Where(Iterable<T> iterable) {
this.iterable = iterable;
}
public SelectOrderBy<T> where(Predicate<T> predicate) {
return new SelectOrderBy<T>( Iterables.filter(iterable, predicate));
}
}
}
поэтому я мог бы создавать коллекции запросов более лаконичным и читабельным способом.
Iterable<? extends NewOrder > currentlyAssigned =
IterableQuery.
from(orders).
where(placedInLast10Days).
orderBy(lastName).
select(orderToNewOrder);
Меня беспокоит, не вызовет ли этот подход взрыв мини-объектов и некоторые проблемы со сборкой мусора (или какие-либо другие проблемы)?
Решение
Я считаю, что Google Collections использует отложенное выполнение для большинства своих итераторов.Отложенное выполнение сведет к минимуму количество создаваемых промежуточных объектов, поскольку устранит большинство промежуточных/временных списков, которые могут быть созданы для каждого вызова (where, orderby и т. д.).
По сути, каждый элемент, возвращаемый currentAssigned.iterator(), не вычисляется, пока вы не вызовете iterator.next().До тех пор ваша итерация currentAssigned — это просто набор операций, не более того.
Ваша единственная забота о взрыве мини-объектов, если эти объекты существуют дольше, чем продолжительность операции с одним элементом...В этом случае пиковое использование памяти может стать довольно большим, и у вас может возникнуть нехватка памяти в очень больших списках или при преобразовании объектов (т. е.вызов ToUpper() для всех строк или чего-то еще).Это будет иметь место только в том случае, если результатомwhere() будет другой список, а затем orderby() создаст другой список, и так далее, и так далее.
Что касается GC, обрабатывающего множество недолговечных объектов, проблем нет.Современный сборщик мусора Java сильно оптимизирован для обработки именно такого поведения.
Другие советы
Я думаю, это зависит от того, как ведет себя преобразование, если оно похоже на ленивый фильтр, т.е.вы не прикрепляете ссылку к каждому результату.тогда это более чем нормально с точки зрения подсчета объектов.Что касается сборки мусора, вы не сохраняете никаких скрытых ссылок, как только вы потеряете корневую ссылку, весь граф станет недоступным и будет собран.вот так, чувак, это действительно здорово.
Сборщик мусора имеет специальный код для недолговечных объектов, и его использование очень дешево.Обычно время от времени все доступные молодые объекты помечаются, и каждый второй объект восстанавливается одним махом.