Я ищу краткую возможность найти набор значений атрибутов, которые минимальны или максимальны в данном потоке объектов.Java: найти несколько значений атрибутов min/max в потоке с использованием lambda
Например:
class Dimensions {
final int startX, startY, endX, endY; //Set by constructor
}
/**
* For the given dimensions, looks where the dimensions intersect.
* These coordinates define the sub-array, which is applied to the given function.
*
* @return the value returned by applying the sub-array in the given dimensions to the given function
*/
<S, T> T performOnIntersections(Function<S, T> function, S[][] inputArray, Dimensions...dimensions){
int maxStartX = Arrays.stream(dimensions).max(Comparator.comparingInt(d -> d.startX)).get().startX;
int maxStartY = Arrays.stream(dimensions).max(Comparator.comparingInt(d -> d.startY)).get().startY;
int minEndX = Arrays.stream(dimensions).min(Comparator.comparingInt(d -> d.endX)).get().endX;
int minEndY = Arrays.stream(dimensions).min(Comparator.comparingInt(d -> d.endY)).get().endY;
return applyInBetween(inputArray, function, maxStartX, maxStartY, minEndX, minEndY);
}
Это очень избыточное, так как я должен создать новый поток для каждого минимального/максимального атрибута мне нужно.
В моей утилите подобный метод является частью рекурсивного алгоритма экспоненциальных затрат, поэтому наличие параллельного решения, которое открывает поток только один раз, будет большим. Еще лучше было бы решение, которое работает над существующим потоком без прекращения (но я сомневаюсь, что это возможно).
У вас есть идея, как улучшить его?
EDIT: Я забыл упомянуть, что Dimension
неизменен, что актуально при использовании Supplier
.
EDIT 2: Вызов collect()
на потоке с помощью лямбда-выражения, а не создание экземпляра DimensionsMinMaxCollector
имеет лучшую производительность во время выполнения. jessepeng упомянул об этом первым, поэтому я отметил его должность как решение. Моя реализация в настоящее время:
return Arrays.stream(dimensions)
.collect(() -> new int[4], (array, dimension) -> {
array[0] = Math.max(array[0], dimension.startX);
array[1] = Math.min(array[1], dimension.endX);
array[2] = Math.max(array[2], dimension.startY);
array[3] = Math.min(array[3], dimension.endY);
}, (a, b) -> {
a[0] = Math.max(a[0], b[0]);
a[1] = Math.min(a[1], b[1]);
a[2] = Math.max(a[2], b[2]);
a[3] = Math.min(a[3], b[3]);
});
Я не думаю, что это можно использовать с помощью Streams, поскольку они могут использоваться только один раз. Чтобы сделать несколько вещей сразу, вы можете использовать старую схему для каждого цикла. – marknorkin
Может быть другой вариант, например 'dimArray = Arrays.asList (размеры);', а затем попытка как 'Collections.max (dimArray, Comparator.comparingInt (d -> d.startX))' etc? –