【发布时间】:2018-02-05 16:41:01
【问题描述】:
我必须为 Iterator 接口编写一个实现。
它的构造函数应该如下所示:
public BlockIterator(Iterator<List<String>> iterator, String regex) {
长话短说,这个实现应该解析巨大的文件,因此不能将它保存到内存中(比如存储和处理到数组或集合),一切都应该“即时”操作。
另外,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()调用后,我们应该只返回匹配子列表(因为不再有文本)。
在这种情况下我找不到有效的解决方案。
有什么建议吗?
【问题讨论】:
-
调用
iterator.hasNext()后,您将更改iterator的状态,并且无法在hashNext和next方法中重复使用它。也许您需要使用Iterable< List<String> >并在您的hasNext和next调用中创建一个新的迭代器。 -
@tsolakp 我无法更改实施条件。不知何故必须使用现有的选项。
标签: java unit-testing iterator implementation