java8
public class CustomDate{
LocalDateTime datetime;
}
List<CustomDate> list = // 2 dates with multiple times我想按日对日期进行分组,并按下列时间对值进行分组,以CustomDate作为值?
Map<LocalDate, List<CustomDate>> map =
list.stream().groupingBy(d-> d.datetime.toLocalDate())任何帮助都是非常感谢的。
发布于 2018-05-19 23:45:25
public class Dates {
private static List< CustomDate > list = new ArrayList<>( );
public static void main( String[] args ) {
Map< LocalDate, List< LocalTime > > result2 = list.stream()
.map( CustomDate::getDatetime )
.collect(
HashMap::new,
Dates::accept,
Dates::merge
);
}
private static void accept( HashMap< LocalDate, List< LocalTime > > map, LocalDateTime date ) {
map.putIfAbsent( date.toLocalDate( ), new ArrayList<>())
.add( date.toLocalTime( ) );
}
private static void merge( Map< LocalDate, List< LocalTime > > map1, Map< LocalDate, List< LocalTime > > map2 ) {
map2.forEach( (date,timeList) -> {
map1.merge( date, timeList, ( l1, l2 ) -> {
l1.addAll( l2 );
return l1;
} );
});
}
}或者简单地说:
Map< LocalDate, List< LocalTime > > result2 = list.stream()
.map( CustomDate::getDatetime )
.collect(
HashMap::new,
(map,date) -> {
map.putIfAbsent( date.toLocalDate( ), new ArrayList<>( )).add( date.toLocalTime( ) );
},
(map1, map2) -> {
map2.forEach( (date,timeList) -> {
map1.merge( date, timeList, ( l1, l2 ) -> {
l1.addAll( l2 );
return l1;
} );
});
}
);这样做的方式不是声明性地调用3次收集器静态方法,而是提供了更多的控制来命令行为,比如为数组使用初始大小、使用特定列表等等,而不会丢失声明式样式带来的糖。
Map< LocalDate, List< LocalTime > > result2 = list.stream()
.map( CustomDate::getDatetime )
.collect(
TreeMap::new,
(map,date) -> {
map.putIfAbsent( date.toLocalDate( ), new ArrayList<>( 800 )).add( date.toLocalTime( ) );
},
(map1, map2) -> {
map2.forEach( (date,timeList) -> {
map1.merge( date, timeList, ( l1, l2 ) -> {
l1.addAll( l2 );
return l1;
} );
});
}
);当然,如果默认行为是可以接受的,这就简单得多:
Map<LocalDate, List<LocalTime>> result = list.stream()
.map( CustomDate::getDatetime )
.collect(groupingBy(LocalDateTime::toLocalDate,
mapping(LocalDateTime::toLocalTime,toList())));另一种方法是定义您自己的收集器,这是我通常喜欢的。通过这样做,您可以同时获得控制和对逻辑进行声明编码的能力,并在需要时进行重用。
这将使您的代码减少到:
Map< LocalDate, List< LocalTime > > result2 = list.stream()
.collect(
customDateCollector()
);如果你有这样的东西:
class CustomDateCollector implements Collector<CustomDate, Map< LocalDate, List< LocalTime > >, Map< LocalDate, List< LocalTime > >> {
@Override
public Supplier< Map< LocalDate, List< LocalTime > > > supplier( ) {
return HashMap::new;
}
@Override
public BiConsumer< Map< LocalDate, List< LocalTime > >, CustomDate > accumulator( ) {
int goodStartUsingProblemKnowledge = 30;
return (map, customDate) -> map.putIfAbsent( customDate.getDatetime().toLocalDate(), new ArrayList<>( goodStartUsingProblemKnowledge) )
.add( customDate.getDatetime().toLocalTime() );
}
@Override
public BinaryOperator< Map< LocalDate, List< LocalTime > > > combiner( ) {
return (map1, map2) -> {
map2.forEach( (date,timeList) -> {
map1.merge( date, timeList, ( list1, list2 ) -> {
list1.addAll( list2 );
return list1;
} );
});
return map1;
};
}
@Override
public Function< Map< LocalDate, List< LocalTime > >, Map< LocalDate, List< LocalTime > > > finisher( ) {
return Function.identity();
}
@Override
public Set< Characteristics > characteristics( ) {
return Collections.unmodifiableSet( EnumSet.of( IDENTITY_FINISH, UNORDERED,CONCURRENT) );
}
public static CustomDateCollector customDateCollector(){
return new CustomDateCollector();
}
}发布于 2018-05-17 18:49:33
您似乎希望按日期进行分组,并将映射值作为LocalTime而不是CustomDate。
Map<LocalDate, List<LocalTime>> result = list.stream()
.collect(Collectors.groupingBy(e -> e.getDatetime().toLocalDate(),
Collectors.mapping(e -> e.getDatetime().toLocalTime(),
Collectors.toList())));发布于 2018-05-17 19:14:22
正如Aominè的回答一样,您应该使用Collectors.groupingBy()。但我建议你做一些额外的步骤。
1使用一些通用代码四值化创建GroupUtils类:
public final class GroupUtils {
public static <K, V> Map<K, List<V>> groupMultipleBy(Collection<V> data, Function<V, K> classifier) {
return groupMultipleBy(data, classifier, Function.identity());
}
public static <K, V, S> Map<K, List<S>> groupMultipleBy(Collection<V> data, Function<V, K> classifier, Function<V, S> mapper) {
return Optional.ofNullable(data).orElse(Collections.emptyList()).stream()
.collect(Collectors.groupingBy(classifier, Collectors.mapping(mapper, Collectors.toList())));
}
}这是我的一个项目的例子。这里我有更多类似的方法。
2在本地文件中,创建具体的方法,使客户端代码的可读性大大提高。
class Client {
public static void main(String... args) {
List<CustomDate> list = Collections.emptyList();
Map<LocalDateTime, List<CustomDate>> map = groupByDatetime(list);
}
private static Map<LocalDateTime, List<CustomDate>> groupByDatetime(List<CustomDate> list) {
return GroupUtils.groupMultipleBy(list, CustomDate::getDatetime);
}
}我相信这是一些更多的代码,但比:
Map<LocalDate, List<LocalTime>> result = list.stream()
.collect(Collectors.groupingBy(e -> e.getDatetime().toLocalDate(),
Collectors.mapping(e -> e.getDatetime().toLocalTime(),
Collectors.toList())));https://stackoverflow.com/questions/50398518
复制相似问题