Iterator<List<String>> 的实现无法正常工作
Implementation for Iterator<List<String>> doesn't work correctly
我必须为 Iterator 接口编写一个实现。
它的构造函数应该如下所示:
public BlockIterator(Iterator<List<String>> iterator, String regex) {
长话短说,这个实现要解析超大文件,不能存入内存(比如存储处理成数组或集合),一切都要操作"on the fly"。
此外,next()
实现应该 return 从第一次出现的模式到下一个出现的子列表。但是,不应包括下一个。
再注意一下,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()
调用之后,我们应该 return 只匹配子列表(因为不再有文本)。
在这种情况下我找不到有效的解决方案。
有什么建议吗?
您可以在字段中存储匹配的列表,将其与 hasNext
中的空值进行比较,并将 return 值与 next
中的值进行比较
试过玩这个,不确定这是否是你的意思,但它通过了你的测试,所以......它是东西!我不明白你的第二次失败,我不确定当内部列表超过 1 个单词时你想要发生什么,但无论如何试试这个:
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) {
...),不要恨我。
我必须为 Iterator 接口编写一个实现。
它的构造函数应该如下所示:
public BlockIterator(Iterator<List<String>> iterator, String regex) {
长话短说,这个实现要解析超大文件,不能存入内存(比如存储处理成数组或集合),一切都要操作"on the fly"。
此外,next()
实现应该 return 从第一次出现的模式到下一个出现的子列表。但是,不应包括下一个。
再注意一下,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()
调用之后,我们应该 return 只匹配子列表(因为不再有文本)。
在这种情况下我找不到有效的解决方案。
有什么建议吗?
您可以在字段中存储匹配的列表,将其与 hasNext
中的空值进行比较,并将 return 值与 next
试过玩这个,不确定这是否是你的意思,但它通过了你的测试,所以......它是东西!我不明白你的第二次失败,我不确定当内部列表超过 1 个单词时你想要发生什么,但无论如何试试这个:
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) {
...),不要恨我。