以下流操作会生成Stream<DateCount>
,其中每个元素表示具有关联计数的日期序列。如果我有星期一到星期日的元素,并且我想将星期五,星期六或星期日汇总成一个新的DateCount
元素,我将如何实现这一目标?最终,我得到的流应该只包含星期一到星期五的元素,但星期五的计数应该是星期五,星期六和星期日的计数总和。我想我需要为此创建Collector
,但我不确定如何让收藏家返回我正在寻找的内容。
IntStream.range(0, days)
.mapToObj(idx -> new DateTime().withTimeAtStartOfDay().minusDays(idx).toDate())
.map(date -> {
Tuple<Date, Long> dateLongTuple = data.stream()
.map(arr -> new Tuple<>(DateTime.parse(arr[0].toString(), DATE_FORMATTER).toDate(), (Long) arr[1]))
.filter(tuple -> date.equals(tuple.getX()))
.findFirst().orElse(new Tuple<>(date, 0L));
return new DateCount(dateLongTuple.getX(), dateLongTuple.getY());
})
答案 0 :(得分:1)
List<IntPair<DayOfWeek>> result = Arrays.stream(DayOfWeek.values())
.map(day -> new IntPair<>(day, 1))
.collect(ArrayList::new,
(list, pair) -> {
switch (pair.x) {
case SATURDAY:
case SUNDAY:
list.get(list.size() - 1).add(pair.y);
break;
default:
list.add(pair);
}
},
ArrayList::addAll);
System.out.println(result);
我的元组实现:
class IntPair<T> {
T x;
int y;
IntPair(T x, int y) {
this.x = x;
this.y = y;
}
void add(int i) {
y += i;
}
@Override
public String toString() {
return "(" + x + ", " + y + ")";
}
}
答案 1 :(得分:1)
您的问题有点不明确:
DateCount
,但在您的代码示例中使用了Tuple<Date, Long>
。也许你有一个“XY Problem”。
我将给你一个使用Java 8 API的例子,它可能更接近你的实际任务(利用your other question的信息):
BigInteger
和Long
个对象的二维数组中创建一个流,我假设它代表日历日和计数long
值SATURDAY
和SUNDAY
视为FRIDAY
,形成一个群组...
long min = LocalDate.now().getLong(ChronoField.EPOCH_DAY),
max=min+DayOfWeek.values().length;
Map<DayOfWeek, Long> map = data.stream()
.map(arr -> new Tuple<TemporalAccessor,Long>(
DateTimeFormatter.BASIC_ISO_DATE.parse(arr[0].toString()), (Long)arr[1]))
.filter(t->{ long d=t.getX().getLong(ChronoField.EPOCH_DAY); return d>=min&&d<max;})
.collect(groupingBy(t -> weekdayOrFriday(t.getX()), summingLong(t -> t.getY())));
System.out.println(map);
static DayOfWeek weekdayOrFriday(TemporalAccessor d) {
final DayOfWeek day = DayOfWeek.from(d);
switch(day) {
default: return day;
case SATURDAY: case SUNDAY: return DayOfWeek.FRIDAY;
}
}
这是一个替代解决方案,它将分组到日历日(在周末天数折叠到前一个星期五之后),如果范围可能大于一周并且您实际上并不想汇总相同的工作日,这将是正确的解决方案
LocalDate min=LocalDate.now(), max=min.plusDays(DayOfWeek.values().length);
data.stream()
.map(arr -> new Tuple<TemporalAccessor,Long>(
DateTimeFormatter.BASIC_ISO_DATE.parse(arr[0].toString()), (Long)arr[1]))
.map(t->new Tuple<LocalDate,Long>(fridayarize(t.getX()), t.getY()))
.filter(t -> !t.getX().isBefore(min) && t.getX().isBefore(max) )
.collect(groupingBy(Tuple::getX, TreeMap::new, summingLong(Tuple::getY)))
.forEach((date,count)->System.out.println(date+"\t: "+count));
static LocalDate fridayarize(TemporalAccessor d) {
LocalDate date = LocalDate.from(d);
switch(DayOfWeek.from(d)) {
default: return date;
case SATURDAY: return date.minusDays(1);
case SUNDAY: return date.minusDays(2);
}
}
但是,在您对实际问题做出更准确的描述之前,我将不再发布更多解决方案......