选项1:
如果您的简历已经按日期排序,您可以实现一个组读取器,它会读取行直到键值发生更改。之后,整个组可以作为一项传递给处理器。
这样的小组阅读器可能如下所示:
private SingleItemPeekableItemReader<I> reader;
private ItemReader<I> peekReaderDelegate;
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(peekReaderDelegate, "The 'itemReader' may not be null");
this.reader= new SingleItemPeekableItemReader<I>();
this.reader.setDelegate(peekReaderDelegate);
}
@Override
// GroupDTO is just a simple container. It is also possible to use
// List<I> instead of GroupDTO<I>
public GroupDTO<I> read() throws Exception {
State state = State.NEW; // a simple enum with the states NEW, READING, and COMPLETE
GroupDTO<I> group = null;
I item = null;
while (state != State.COMPLETE) {
item = reader.read();
switch (state) {
case NEW: {
if (item == null) {
// end reached
state = State.COMPLETE;
break;
}
group = new GroupDTO<I>();
group.addItem(item);
state = State.READING;
I nextItem = reader.peek();
// isGroupBreak returns true, if 'item' and 'nextItem' do NOT belong to the same group
if (nextItem == null || getGroupBreakStrategy.isGroupBreak(item, nextItem)) {
state = State.COMPLETE;
}
break;
}
case READING: {
group.addItem(item);
// peek and check if there the peeked entry has a new date
I nextItem = peekEntry();
// isGroupBreak returns true, if 'item' and 'nextItem' do NOT belong to the same group
if (nextItem == null || getGroupBreakStrategy.isGroupBreak(item, nextItem)) {
state = State.COMPLETE;
}
break;
}
default: {
throw new org.springframework.expression.ParseException(groupCounter, "ParsingError: Reader is in an invalid state");
}
}
}
return group;
}
您需要一个 SingleItemPeekableItemReader,以便预读取下一个元素。这一篇涵盖了您的普通读者。
选项2:
第一步正如您所建议的,但只需为步骤 2 编写一个 tasklet。无需使用读取器-进程-编写器方法,而是可以使用一个简单的 tasklet 将映射的内容写入文件。
选项 3:
如果您确实想在步骤 2 中使用读取器-处理器-写入器方法,请编写您自己的读取器来迭代您的映射。
类似的东西(我没有测试该代码):
public class MapReader implements ItemReader {
private MapContainer container;
private Iterator<Map.Entry<Date, Integer> mapIterator;
@PostConstruct
public void afterPropertiesSet() {
Assert.notNull(container);
iterator = container.getMap().entry().iterator;
}
public void setMapContainer(MapContainer container) {
this.container = container;
}
public Map.Entry<Date, Integer> read() {
if (iterator.hasNext()) {
return iterator.next();
}
return null;
}
}
@Component
public class MapContainer {
private Map<Date, Integer> data = new Hashmap<>();
public Map<Date, Integer> getMap() {
return data;
}
// add modifier method as needed for step 1
}
因此,您为容器创建一个 spring-bean 实例,将其注入到步骤 2 的处理器中,在那里填充,同时将其注入到上面的阅读器中。