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 中的空值进行比较,并将 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) {...),不要恨我。