max
/min
은 고유 한 반면, 당연히 argMax
/argMin
은 보장 할 수 없습니다. 이것은 특히 감소 유형이 컬렉션 (예 : List
)과 같아야 함을 의미합니다. 위에서 제안한 것보다 더 많은 작업이 필요합니다.
다음의 ArgMaxCollector<T>
클래스는 이러한 감소의 간단한 구현을 제공합니다. main
는 클래스의 응용 프로그램이 자신의 길이에 의해 정렬 된 문자열
one two three four five six seven
세트의 argMax
/argMin
을 계산하는 방법을 보여줍니다. (각각 argMax
및 argMin
수집 결과를보고)의 출력은 두 개의 길고 짧은 세 문자열 각각 것을
[three, seven]
[one, two, six]
이어야한다.
이것은 새로운 Java 8 스트림 API 사용에 대한 나의 첫 번째 시도이므로 모든 설명이 환영받을 것입니다.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collector;
class ArgMaxCollector<T> {
private T max = null;
private ArrayList<T> argMax = new ArrayList<T>();
private Comparator<? super T> comparator;
private ArgMaxCollector(Comparator<? super T> comparator) {
this.comparator = comparator;
}
public void accept(T element) {
int cmp = max == null ? -1 : comparator.compare(max, element);
if (cmp < 0) {
max = element;
argMax.clear();
argMax.add(element);
} else if (cmp == 0)
argMax.add(element);
}
public void combine(ArgMaxCollector<T> other) {
int cmp = comparator.compare(max, other.max);
if (cmp < 0) {
max = other.max;
argMax = other.argMax;
} else if (cmp == 0) {
argMax.addAll(other.argMax);
}
}
public List<T> get() {
return argMax;
}
public static <T> Collector<T, ArgMaxCollector<T>, List<T>> collector(Comparator<? super T> comparator) {
return Collector.of(
() -> new ArgMaxCollector<T>(comparator),
(a, b) -> a.accept(b),
(a, b) ->{ a.combine(b); return a; },
a -> a.get()
);
}
}
public class ArgMax {
public static void main(String[] args) {
List<String> names = Arrays.asList(new String[] { "one", "two", "three", "four", "five", "six", "seven" });
Collector<String, ArgMaxCollector<String>, List<String>> argMax = ArgMaxCollector.collector(Comparator.comparing(String::length));
Collector<String, ArgMaxCollector<String>, List<String>> argMin = ArgMaxCollector.collector(Comparator.comparing(String::length).reversed());
System.out.println(names.stream().collect(argMax));
System.out.println(names.stream().collect(argMin));
}
}
가! 마지막에 원시'get()'을 사용하지 말라. 그렇지 않으면 스트림이 비어 있다면 NSEE를 던질 것이다. 'orElse','orElseThrow' 또는'ifPresent'와 같은 안전한 메소드를 사용하십시오. –
@BrianGoetz 브라이언 알레르기 중 하나를 발견했다고 생각합니다. 그는'Optional.get()'을 작성할 때마다 재채기를합니다. –
@StuartMarks 그렇습니다. 우리는 결코 그것을 'get'이라고 부르면 안된다. 우리는 그것을'getOrThrow()'또는'orElseThrow()'또는'getUnsafely()'또는 아마도'getOrThrowNoSuchElementExcpetionIfThisOptionalIsNotPresent()'로 불렀어야합니다. –