java - do-while with Java8-Optional

标签 java loops while-loop java-8 option-type

我经常在我的一些项目中使用 do-while-checkNextForNull-getNext 循环模式(不知道是否有正式名称)。但是在 Java8 中,使用 Optional 被认为是比在客户端代码中检查空引用更干净的代码。但是当在这种循环模式中使用 Optional 时,代码变得有点冗长和丑陋,但是因为 Optional 有一些方便的方法,我希望一定存在比我在下面提出的方法更简洁的方法。

例子:

给定以下类(class)。

class Item {
    int nr;

    Item(nr) {
        this.nr = nr;
        // an expensive operation
    }

    Item next() {
        return ...someCondition....
            ? new Item(nr + 1)
            : null;
    }
}

其中第一个项目总是有 nr==1 并且每个项目决定下一个项目,并且您不想创建不必要的新项目。

我可以在客户端代码中使用以下循环 do-while-checkNextForNull-getNext 模式:

Item item = new Item(1);
do {
    // do something with the item ....
} while ((item = item.next()) != null);

使用 Java8-Optional,给定的类变为:

class Item {
    ....

    Optional<Item> next() {
        return ...someCondition....
            ? Optional.of(new Item(nr + 1))
            : Optional.empty();
    }
}

然后 do-while-checkNextForNull-getNext 循环模式变得有点丑陋和冗长:

Item item = new Item(1);
do {
    // do something with the item ....
} while ((item = item.next().orElse(null)) != null);

orElse(null)) != null 部分感觉不舒服。

我一直在寻找其他类型的循环,但没有找到更好的循环。有更清洁的解决方案吗?

更新:

可以使用 for-each 循环同时避免空引用(使用空引用被认为是一种不好的做法)。该解决方案由 Xavier Delamotte 提出,不需要 Java8-Optional。

使用通用迭代器实现:

public class Item implements Iterable<Item>, Iterator<Item> {
    int nr;

    Item(int nr) { 
        this.nr = nr;
        // an expensive operation
    }

    public Item next() {
        return new Item(nr + 1);
    }

    public boolean hasNext() {
        return ....someCondition.....;
    }

    @Override
    public Iterator<Item> iterator() {
        return new CustomIterator(this);
    }
}

class CustomIterator<T extends Iterator<T>> implements Iterator<T> {
    T currentItem;
    boolean nextCalled;

    public CustomIterator(T firstItem) {
        this.currentItem = firstItem;
    }

    @Override
    public boolean hasNext() {
        return currentItem.hasNext();
    }

    @Override
    public T next() {
        if (! nextCalled) {
            nextCalled = true;
            return currentItem;
        } else {
            currentItem = currentItem.next();
            return currentItem;
        }
    }
}

然后客户端代码变得非常简单/干净:

for (Item item : new Item(1)) {
    // do something with the item ....
}

虽然这可能被视为违反迭代器契约,因为 new Item(1) 对象包含在循环中,而通常情况下,for 循环会立即调用 next(),因此跳过第一个对象。换句话说:对于第一个对象,next() 被违反了,因为它返回第一个对象本身。

最佳答案

你可以这样做:

Optional<Item> item = Optional.of(new Item(1));
do {
    Item value = item.get();
    // do something with the value ....
} while ((item = value.next()).isPresent());

或(避免额外的变量):

Optional<Item> item = Optional.of(new Item(1));
do {
    // do something with item.get() ....
} while ((item = item.get().next()).isPresent());

关于java - do-while with Java8-Optional,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28741673/

相关文章:

java - Java 和 PHP 中相同的哈希算法给出不同的结果

java - 如何在JBoss 6.4中禁用javax.validation.api

c# - 如何循环访问通过 Windows 控件访问的选中列表框?

java - 从 For 循环 Java 返回字符串值

java - 找不到DynamoDB地理对象映射器类

java - 为什么数组出现空指针异常?

c++ - 如何返回指向数组中对象的指针?

java - 老师坚持使用 if 语句而不是 while 语句,而 with while 语句我的代码可以工作

java - 从文本文件中检索字符串数据并将其存储到对象中

bash 脚本 : commands after the loop are not executed if the loop condition is false