java 8 agrupación por con recuento diferente

EdeGerSil:
SELECT Count(1) AS total,
          'hello' AS filter,
          field1 AS field1,
          Count(DISTINCT field2) AS total_field2
   FROM table
   WHERE field = true
     AND status = 'ok'
      GROUP  BY field1

Duda de cómo hacer un mapa mediante java8 para almacenar el siguiente resultado. Clave del mapa debe ser campo field1y el valor del mapa debe ser total_field2campo.

Es decir, necesito grupo de mi lista usando campo1 campo2 campo y cuento campo

Para el campo total que tengo

myList.stream().collect(Collectors.groupingBy(MyObject::getField1, Collectors.counting())) 
// this is just counting the records grouped by field1

Mi resultado es correcto total_field1: {4 = 55, 6 = 31}

Para campo2, necesitaba algo como esto, pero es sólo darme un registro

myList.stream().filter(distinctByKey(MyObject::getField2))
.collect(Collectors.groupingBy(MyObject::getField1, Collectors.counting()));

public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

Resultado total_Field2: {4 = 31}

debe me volver 2 ejemplo registra total_Field2: {4 = 31, 6 = 31}

Ejemplo @Naman

public static <T, A, R> Collector<T, ?, R> filtering(
        Predicate<? super T> predicate, Collector<? super T, A, R> downstream) {

        BiConsumer<A, ? super T> accumulator = downstream.accumulator();
        return Collector.of(downstream.supplier(),
            (r, t) -> { if(predicate.test(t)) accumulator.accept(r, t); },
            downstream.combiner(), downstream.finisher(),
            downstream.characteristics().toArray(new Collector.Characteristics[0]));
    }

myList.stream().collect(Collectors.groupingBy(MyObject::getField1, filtering(distinctByKey(MyObject::getField2), Collectors.counting())));
también:

Una alternativa a la respuesta de Deadpool es contar distinctByKeydespués groupingBy field1mientras que el mapeo de entradas y finalmente recoger a una Mapcomo:

Map<String, Long> r = myList.stream()
        .collect(Collectors.groupingBy(MyObject::getField1))
        .entrySet().stream()
        .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(),
                e.getValue().stream().filter(distinctByKey(MyObject::getField2)).count()))
        .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));

Si estuvieras en Java-9 o superior, se podría haber utilizado Collectors.filteringcomo downstreamel Predicatedefinido mediante la utilidad distinctByKey, tales como:

Map<String, Long> result = myList.stream()
        .collect(Collectors.groupingBy(MyObject::getField1,
                Collectors.filtering(distinctByKey(MyObject::getField2),
                        Collectors.counting())));


Nota : Las anteriores dos enfoques son sin embargo muy diferente, los antiguos grupos de todos los elementos de la lista por un campo ( field1) y luego dentro de cada subgrupo encuentra un recuento diferente de otro campo específico ( field2).

Por otra parte, los últimos grupos todos los elementos distintos de la tecla ( field2) y luego estos grupos por otra tecla ( field1) con la reducción de conteo.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=312135&siteId=1
Recomendado
Clasificación