2015-12-08 2 views
2

Я новичок в API интерфейса Java и имею возможность использовать его.Группировка по java 8 Stream API

Map<Object, ? extends Object> map = list.stream().collect(Collectors.groupingBy(p->p.getX() 
                  ,Collectors.groupingBy(p->p.getY() 
                  ,Collectors.groupingBy(p->p.getZ())))); 

Учитывайте, что x, y и z являются атрибутами данного класса. Это отлично работает, если у нас есть порядок группировки (какой атрибут учитывать первым, вторым и так далее ...) предопределен.

(В данной части атрибута кода x считается 1-й, y 2-й и 2-й).

Теперь, в моем случае, порядок группировки не является предопределенным и может меняться во время выполнения. Итак, во время компиляции я не знаю, что пройти в методе сбора. Я ищу решение, с помощью которого я могу прочитать строку конфигурации и изменить группировку во время выполнения.

+0

Что вы подразумеваете под «читать строку конфигурации и изменить группировку в время запуска ".? – Tunaki

+0

ok, допустим, что он определен пользователем, поэтому, если пользователь определяет groupingOrder = x, y, z, он должен быть сгруппирован, как указано выше, если другой пользователь определяет его как y, x, z, он должен соответствующим образом измениться. (* GroupingOrder просто имя, которое я взял для справки) – Sachin

ответ

1

Вы можете создать вспомогательный метод, который строит свой собственный Collector с помощью данной классификации функций: пример

@SuppressWarnings("unchecked") 
@SafeVarargs 
public static <T> Collector<T, ?, Map<?, ?>> multiGrouping(
               Function<? super T, ?>... classifiers) { 
    Collector<T, ?, Map<?, ?>> result = null; 
    for(int i=classifiers.length-1; i>=0; i--) { 
     Collector<?, ?, ?> next; 
     if(result == null) { 
      next = Collectors.groupingBy(classifiers[i]); 
     } else { 
      next = Collectors.groupingBy(classifiers[i], result); 
     } 
     result = (Collector<T, ?, Map<?, ?>>)next; 
    } 
    return result; 
} 

Использования:

Map<?, ?> map = Stream.of("abc", "def", "cd", "cfff") 
         .collect(multiGrouping(String::length, s -> s.charAt(0))); 
+0

Спасибо, получилось .. Я искал то же самое .. – Sachin

1

Предполагая p имеет класс P, вы можете определить порядок, как это:

Function<P, Object> g1 = P::getX; 
Function<P, Object> g2 = P::getX; 
Function<P, Object> g3 = P::getX; 

А потом:

list.stream().collect(Collectors.groupingBy(g1, 
         Collectors.groupingBy(g2, 
          Collectors.groupingBy(g3)))); 

g1, g2, g3 также может быть определена с помощью отражения для доступа метод/поле во время выполнения на основе имени поля/метода.

+0

Спасибо за быстрый ответ. В таком случае мне нужно определить порядок для всех атрибутов? Я думал о построении «Collectors.groupingBy (...» как строки во время выполнения на основе строки конфигурации (например, ** «list.stream(). Collect (Collectors.groupingBy (g1, Collectors.groupingBy (g2, Collectors.groupingBy (g3)))); ** и затем выполнить его с помощью groovy, но похоже, что текущая версия groovy не поддерживает lambda .. – Sachin

Смежные вопросы