簡體   English   中英

迭代器的實現 <List<String> &gt;無法正常工作

[英]Implementation for Iterator<List<String>> doesn't work correctly

我必須為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()調用之后,我們應該僅返回匹配subllist(因為不再有文本)。

在這種情況下,我找不到有效的解決方案。

有什么建議么?

試着玩這個游戲,不確定這是否是您的意思,但是它正在通過您的測試,所以...確實如此! 我不明白您的第二次失敗,也不確定內部列表中的單詞多於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) { ...),不要討厭我。

你可以存儲與匹配列表中的一個字段,用空的比較它hasNext ,和返回值在next

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM