Iterator的实现<list <string>&gt;没有正常工作

时间:2018-02-05 16:41:02

标签: java unit-testing iterator implementation

我必须为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()调用之后,我们应该只返回匹配子菜单(因为不再有文本)。

在这种情况下,我无法找到有效的解决方案。

有什么建议吗?

2 个答案:

答案 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

中返回值