Я пытаюсь оптимизировать функциональную операцию на Java 8 по сравнению с ее процедурным эквивалентом, но у меня возникла серьезная проблема с производительностью.Оптимизация функционального алгоритма Java 8 по сравнению с его процедурной частью счетчика
Ситуация
Я должен разобрать заголовки HTTP String, List<String>
от значения данного перечисления, которые отображающая HeaderName для многих возможных вариантов String, Set<String>
.
Пример
Учитывая следующие HttpHeaders:
public static final Map<String, List<String>> httpHeaders = new HashMap<>();
httpHeaders.put("Content-Type", Arrays.asList("application/json", "text/x-json"));
httpHeaders.put("SID", Arrays.asList("ABC123"));
httpHeaders.put("CORRELATION-ID", Arrays.asList("ZYX666"));
И мой обычай перечисления:
LogHeaders
protected final String key;
protected final Set<String> variation;
SESSION_ID("_sid", Arrays.asList("SESSION-ID", "SID"));
CORRELATION_ID("cid", Arrays.asList("CORRELATION-ID", "CID")),
private LogHeaders(final String logKey, final List<String> logKeyVariations) {
this.logKey = logKey;
this.logKeyVariations = new HashSet<>(logKeyVariations);
}
@Override
public String toString() {
return this.logKey;
}
The R esult должна быть карта «LogHeaders.key» со значением, установленным для соответствующих вариантов из HttpHeaders. Только один вариант возможен для данного заголовка:
// {LogHeaders.key : HttpHeaderValue>
{
_sid=[ABC123],
_cid=[ZYX666]
}
Процедурный код
final Map<String, List<String>> logHeadersToValue = new HashMap<>();
for (final LogHeaders header : LogHeaders.values()) {
for (final String variation : header.getLogKeyVariations()) {
final List<String> headerValue = httpHeaders.get(variation);
if (headerValue != null) {
logHeadersToValue.put(header.logKey, headerValue);
break;
}
}
}
Функциональный код
final Map<String, List<String>> logHeadersToValue =
EnumSet.allOf(LogHeaders.class)
.stream()
.collect(Collectors.toMap(
LogHeaders::toString,
logHeader -> logHeader.getLogKeyVariations().stream()
.map(variation -> httpHeaders.get(variation)).filter(Objects::nonNull)
.collect(singletonCollector())));
public static <T> Collector<T, ?, T> singletonCollector() {
return Collectors.collectingAndThen(Collectors.toList(), list -> {
if (list.size() < 1) {
return null;
}
return list.get(0);
});
}
Текущий Benchmark
FunctionalParsing : 0.086s
ProceduralParsing : 0.001s
У вас есть какие-либо идеи, как Я мог бы оптимизировать свои функции часть?
Спасибо
UPDATE ЭТАЛОН
Я побежал 100k + 100k прогрева итерацию с @Tagir Валеев код:
FunctionalParsing : 0.040s
ProceduralParsing : 0.010s
UPDATE ЭТАЛОН # 2
Я побежал 100k прогрев + 100k итерации с кодом @Misha:
FunctionalParsing : 0.025s
ProceduralParsing : 0.017s
Первый вопрос, очевидно, как вы оцениваете производительность, во-вторых, насколько велики эти коллекции примерно? – biziclop
Вы, кажется, жертва классической ошибки, когда дело доходит до любой новой и блестящей функциональности f: используйте f для использования f, а вы f; ваш старый код работает просто отлично, так зачем пытаться использовать f, когда он явно не имеет преимуществ? – fge
Никто никогда не говорил, что функциональный код работает быстрее. – AlexWien