【问题标题】:How to get the next tree elements of a list如何获取列表的下三个元素
【发布时间】:2015-08-06 02:17:56
【问题描述】:

这个问题更多的是关于最佳实践,而不是从列表中获取元素。

我有一个 ArrayList,但我通过使用一个简单的 for 循环来迭代它。如果出现某个关键字,我需要将下一个树元素与某个模式进行比较。

private static boolean areVectorArgumentsValid(ArrayList<String> fileContent)
{
    for (int i=0; i<fileContent.size(); i++)
    {
        if (fileContent.get(i).equals(NORMAL) || fileContent.get(i).equals(VERTEX))
        {
            // get the next three elements of "fileContent" and see if they match a certain pattern
        }
    }
return true;
}

我的第一种方法是在实际的外部循环中使用另一个 for 循环,然后将 i 增加 3:

for (int j=i+1; j<=i+3; j++)
{
    if (!fileContent.get(j).matches(PATTERN))
    {
        return false;
    }
}
i+=3;

如您所见,让方法做我想做的事情并不难,但是...我不确定是否有一种方法可以让您称之为更优雅.

【问题讨论】:

    标签: java for-loop iteration


    【解决方案1】:

    可以重复3次,获取元素时使用++i

    for (int j = 0; j < 3; j++) {
        if (!fileContent.get(++i).matches(PATTERN)) {
            return false;
        }
    }
    

    或者用流做这样的事情:

    if (fileContent.stream().skip(i).limit(3).anyMatch(s -> !s.matches(PATTERN))) {
        return false;
    }
    i += 3;
    

    但我认为最好的解决方案是完全改变它并使用Iterator

    private static boolean areVectorArgumentsValid(ArrayList<String> fileContent) {
        for (Iterator<String> it = fileContent.iterator(); it.hasNext();) {
            String s = it.next();
            if (!s.equals(NORMAL) && !s.equals(VERTEX)) {
                continue;
            }
            for (int i = 0; i < 3; i++) {
                if (!it.hasNext() || !it.next().matches(PATTERN)) {
                    return false;
                }
            }
        }
        return true;
    }
    

    【讨论】:

    • 一般来说使用迭代器真的更好吗?迭代器如何表现性能?
    • @Vulpecula 取决于列表的类型。例如,当使用LinkedList 时,您应该在迭代时始终使用Iterator,但对于ArrayList,在性能方面没有太大差异。因此,在这种情况下,您可以使用您认为更具可读性的那个。
    【解决方案2】:

    这个问题更多的是关于最佳实践而不是获取元素 来自列表。

    在详细说明之前,先说几句..

    • NORMAL.equals(fileContent.get(i)) 而不是 fileContent.get(i).equals(NORMAL) 将避免 NullPointerException
    • 在迭代下三个元素之前,您应该首先检查您的List 是否有下三个元素以避免ArrayIndexOutOfBoundException

    现在如果只检查接下来的三个元素,并且只在三个元素中的任何一个与模式不匹配时才返回 false,那么您可以有类似以下的内容,

       if (fileContent.size() < i + 3 
        && (!fileContent.get(i+1).matches(PATTERN)
            || !fileContent.get(i+2).matches(PATTERN) 
            || !fileContent.get(i+3).matches(PATTERN))) {
            return false;
       }
    

    问题在这种方法中它不会检查您的列表是否没有接下来的三个元素。

    至于通过允许检查下一个可用元素的方法,您可以在调用 @987654327 之前添加一个条件来检查您的列表是否在 loop 中是否有下一个元素@ 方法在列表中。您迭代下三个元素的方法似乎很好,但需要进行以下改进。

    for (int j=i+1; j<=i+3; j++){
        if (fileContent.size() < j && !fileContent.get(j).matches(PATTERN)){
            return false;
        } else {
            break;
        }
    }
    

    【讨论】:

    • 而不是添加对接下来三个元素的检查,for循环只能到n-3,其中n是列表的长度
    • 感谢您的意见。 Bot 现在有很多关于如何处理这个问题的答案,我有点困惑。 :) 最简单的方法可能是坚持使用内部 for 循环,但使用流和 lambda 和/或 Iterator 看起来很有趣。
    【解决方案3】:

    你可以通过引入一个状态只用一个循环来做到这一点:

    private static boolean areVectorArgumentsValid(ArrayList<String> fileContent)
    {
        int state = 0;
        for (int i=0; i<fileContent.size(); i++)
        {
             switch (state) {
             case 0:
                 if (fileContent.get(i).equals(NORMAL) || fileContent.get(i).equals(VERTEX))
                     state++;
                 break;
             case 1:
             case 2:
             case 3:
                 if (!fileContent.get(i).matches(PATTERN))
                     return false;
                 state = (state + 1) % 4;
                 break;
        }
        return true;
    }
    

    【讨论】:

      【解决方案4】:

      在我看来,你应该创建一个方法,从数组和索引开始查找,如果它与这三个匹配,则返回布尔值。这是优雅的方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-31
        • 1970-01-01
        • 2020-05-22
        • 1970-01-01
        • 1970-01-01
        • 2015-08-13
        相关资源
        最近更新 更多