我必须为Iterator接口编写一个实现。
它的构造函数应如下所示:
public BlockIterator(Iterator<List<String>> iterator, String regex) {
总而言之,这个实现应该解析大尺寸的文件,因此无法将其保存到内存中(如存储和处理到数组或集合),所有内容都应该被操作&#34;飞&#34;
此外,next()
实现应该从第一次出现的模式返回到下一个模式的子列表。但是,不应该包括下一个。
再一次注意,hasNext()
应该是幂等的。即使在20次通话之后,结果应该是相同的。
这是我的测试解决方案:
import com.google.common.collect.Lists;
import org.junit.Test;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
class BlockIterator implements Iterator<List<String>> {
private final Iterator<List<String>> iterator;
private final Pattern pattern;
public BlockIterator(Iterator<List<String>> iterator, String regex) {
this.iterator = iterator;
this.pattern = Pattern.compile(regex);
}
@Override
public boolean hasNext() {
while (iterator.hasNext()) {
List<String> line = iterator.next();
for (String word : line) {
Matcher matcher = pattern.matcher(word);
if (matcher.find()) {
return true;
}
}
}
return false;
}
@Override
public List<String> next() {
String matchWord = null;
List<String> result = Lists.newArrayList();
while (iterator.hasNext()) {
List<String> line = iterator.next();
for (String word : line) {
Matcher matcher = pattern.matcher(word);
if (matcher.find()) {
if (null != matchWord) {
return result;
} else {
matchWord = word;
}
}
if (null != matchWord) {
result.add(word);
}
}
}
return result;
}
}
public class BlockIteratorTest {
public static final List<List<String>> lines = Lists.newArrayList(
Lists.newArrayList("123"),
Lists.newArrayList("- test -"),
Lists.newArrayList("start"),
Lists.newArrayList("end"),
Lists.newArrayList("test123"));
@Test
public void testNext() throws Exception {
List<String> expectedFirstNext = Lists.newArrayList("- test -", "start", "end");
List<String> expectedSecondNext = Lists.newArrayList("test123");
BlockIterator blockIterator = new BlockIterator(lines.iterator(), "test");
List<String> actualFirstNext = blockIterator.next();
assertEquals(expectedFirstNext, actualFirstNext);
List<String> actualSecondNext = blockIterator.next();
assertEquals(expectedSecondNext, actualSecondNext);
}
@Test
public void testHasNext() throws Exception {
BlockIterator blockIterator = new BlockIterator(lines.iterator(), "test");
for (int i = 0; i < 20; i++) {
assertTrue(blockIterator.hasNext());
}
}
}
很少失败:
hasNext()
并非幂等next()
调用之后,我们应该只返回匹配子菜单(因为不再有文本)。在这种情况下,我无法找到有效的解决方案。
有什么建议吗?
答案 0 :(得分:2)
尝试玩这个,不确定这是不是你的意思,但是它通过了你的测试,所以......它是一些东西!我不明白你的第二次失败,我不确定当内部列表有多个单词时你想要发生什么,但是无论如何都要尝试:
class IteratorTesting implements Iterator<List<String>> {
private final Iterator<List<String>> iterator;
private final Pattern pattern;
private boolean hasNext = false;
private List<String> next = null;
private String startNext = null;
public IteratorTesting(Iterator<List<String>> iterator, String regex) {
this.iterator = iterator;
this.pattern = Pattern.compile(regex);
hasNext = checkNext();
}
@Override
public boolean hasNext() {
return hasNext;
}
private boolean checkNext() {
String matchWord = null;
List<String> result = new ArrayList<>();
if(startNext != null)
result.add(startNext);
while(iterator.hasNext()) {
List<String> line = iterator.next();
for(String word : line) {
Matcher matcher = pattern.matcher(word);
if(matcher.find()) {
if(null != matchWord || startNext != null) {
next = result;
startNext = word;
return true;
} else {
matchWord = word;
}
}
if(null != matchWord || startNext != null) {
result.add(word);
}
}
}
next = result;
startNext = null;
return !next.isEmpty();
}
@Override
public List<String> next() {
List<String> current = next;
hasNext = checkNext();
return current;
}
}
我知道这是不好的代码,我现在看到的东西可以立即重构(if(null != matchWord || startNext != null) {
...),不要讨厌我。
答案 1 :(得分:0)
您可以在字段中存储匹配的列表,将其与hasNext
中的null进行比较,并在next