使用 Java8-Optional 做时 [英] do-while with Java8-Optional

查看:42
本文介绍了使用 Java8-Optional 做时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm frequently using the do-while-checkNextForNull-getNext looping pattern (don't know if there is an official name for it) in some of my projects. But in Java8, the use of Optional is considered as cleaner code than checking for null references in client-code. But when using Optional in this looping pattern, the code gets a bit verbose and ugly, but because Optional has some handy methodS, I would expect that there must exist a cleaner way than the one I came up with below.

示例:

给定以下类.

class Item {
    int nr;

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

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

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

In which the first item always has nr==1 and each item determines the next item, and you don't want to create unnecessary new items.

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

I can use the following looping do-while-checkNextForNull-getNext pattern in client-code:

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

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

With Java8-Optional, the given class becomes:

class Item {
    ....

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

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

And then the do-while-checkNextForNull-getNext looping pattern becomes a bit ugly and verbose:

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

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

我已经寻找了其他类型的循环,但没有找到更好的.有没有更干净的解决方案?

I have looked for other kind of loops, but haven't found a better one. Is there a cleaner solution?

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

It is possible to use a for-each loop while at the same time avoiding null-references (the use of null-references is considered as a bad practice). This solution has been proposed by Xavier Delamotte, and doesn't need 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;
        }
    }
}

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

Then client code becomes very simple/clean:

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

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

Although this may be seen as a violation of the Iterator contract because the new Item(1) object is included in the loop, whereas normally, the for loop would immediately call next() and thus skipping the first object. In other words: for the first object, next() is violated because it returnS the first object itself.

推荐答案

你可以这样做:

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

或(避免额外的变量):

or (to avoid the extra variable) :

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

这篇关于使用 Java8-Optional 做时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆