Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 这个循环代码可以简化吗?_Java_Java 8 - Fatal编程技术网

Java 这个循环代码可以简化吗?

Java 这个循环代码可以简化吗?,java,java-8,Java,Java 8,我有个问题。。。基本上,我的代码很难看,我不喜欢它。我想知道是否有办法简化它(我使用Java8) 我有这些遵循这种模式的“代码块”,我在一个方法中有大约5或6个,所以这个方法看起来非常重复和丑陋 循环都是一样的,只是内部代码不同 有什么办法可以简化这一点吗 代码块示例 String id=null; 对于(int i=0;i

我有个问题。。。基本上,我的代码很难看,我不喜欢它。我想知道是否有办法简化它(我使用Java8)

我有这些遵循这种模式的“代码块”,我在一个方法中有大约5或6个,所以这个方法看起来非常重复和丑陋

循环都是一样的,只是内部代码不同

有什么办法可以简化这一点吗

代码块示例
String id=null;
对于(int i=0;i
例子
String id=null;
对于(int i=0;i25)断裂;
//结束变量代码
//隔着支票睡觉
如果(i
可以使用递归使循环可重用,但这只有在经常使用循环时才有意义

public void loopWithDelay(int numberOfChecks, int delay, Runnable r) { 
   if (numberOfChecks != 0) {
      r.run();
      loopWithDelay(numberOfChecks - 1, delay, r);
      Thread.sleep(DELAY);
   }
}
实际的调用将如下所示:

loopWithDelay(5, 1000, new Runnable() {
                  @Override
                  public void run() {
                     //Variable code goes here
                  }
             });
String id = retryWithDelay(NUM_CHECKS, DELAY, () -> Optional.ofNullable(getPrice()))
                   .orElse(null);
String id = retryWithDelay(NUM_CHECKS, DELAY, () -> getPrice());
AtomicInteger x = new AtomicInteger(1);
Integer result = retryWithDelay(NUM_CHECKS, DELAY, () -> {
    int val = x.get()*2;
    x.set(val);
    return val > 25 ? val : null;
});
一般来说,您确定要在操作后等待延迟秒,还是让操作每隔延迟秒执行一次

编辑: 我很笨,不需要递归,这也很有效:

public void loopWithDelay(int numberOfChecks, int delay, Runnable r) { 
   for (int i = 0; i < numberOfChecks; i++) {
      r.run();
      if (i != numberOfChecks -1)
         Thread.sleep(DELAY);
   }
}
public void loopWithDelay(int numberOfChecks,int delay,Runnable r){
对于(int i=0;i
编写一个包含所有样板文件的抽象代码怎么样

class MyLoop
{
    private int numChecks;

    private int delay;

    public MyLoop(int numChecks, int delay) {...}

    public void loopAndSleep(MyTask task)
    throws InterruptedException
    {
        // Update: It is important to set properly the order of the looping conditions, 
        // to stop invoking hasEnded() as soon as i<numChecks==false (Thaks to Simon Eismann).
        for (int i=0; i<numChecks && !task.hasEnded(); i++)
        {
            if (i < numChecks -1)
            {
                Thread.sleep(DELAY);
            }
        }
    }
}

interface MyTask
{
    public boolean hasEnded();
}

通过正确扩展
MyTask
,您可以为它们指定特定的状态变量。

如果您想尝试某些操作直到返回值可用,您可以执行以下操作(Java-8方式):

或者,如果出于某种原因您不喜欢选项,您可以坚持使用
null

public static <T> T retryWithDelay(int numberOfChecks, int delay,
        Supplier<T> supplier) throws InterruptedException {
    for (int i = 0; i < numberOfChecks; i++) {
        if (i > 0)
            Thread.sleep(delay);
        T result = supplier.get();
        if (result != null)
            return result;
    }
    return null;
}
或使用方法参考:

String id = retryWithDelay(NUM_CHECKS, DELAY, this::getPrice);
请注意,
x=2*x
的第二个示例比较困难,因为它有一些可变状态。它可以用如下肮脏的方式解决:

loopWithDelay(5, 1000, new Runnable() {
                  @Override
                  public void run() {
                     //Variable code goes here
                  }
             });
String id = retryWithDelay(NUM_CHECKS, DELAY, () -> Optional.ofNullable(getPrice()))
                   .orElse(null);
String id = retryWithDelay(NUM_CHECKS, DELAY, () -> getPrice());
AtomicInteger x = new AtomicInteger(1);
Integer result = retryWithDelay(NUM_CHECKS, DELAY, () -> {
    int val = x.get()*2;
    x.set(val);
    return val > 25 ? val : null;
});
然而,我希望这个版本只是为了说明,而不是真正的代码


还有一些更复杂的方法可能会滥用API,但允许更大的灵活性。您可以创建一个数量不断增加的
IntStream
,但它们在给定延迟下可用:

public static IntStream delayedStream(int numberOfChecks, int delay) {
    return IntStream.range(0, numberOfChecks)
                    .peek(x -> {
                        if(x > 0) {
                            try {
                                Thread.sleep(delay);
                            } catch (InterruptedException e) {
                                // ignore
                            }
                        }
                    });
}
因此,第一个问题现在可以解决为:

String id = delayedStream(NUM_CHECKS, DELAY)
                  .mapToObj(x -> getPrice())
                  .filter(Objects::nonNull)
                  .findFirst().orElse(null);
第二个可以这样求解(假设初始
x
值为1):

int x=delayedStream(NUM_检查,延迟)
.map(idx->1 val>25)
.findFirst().orElse(-1);

您提供的结构称为“轮询循环”,您是正确的,这是一种糟糕的编程风格,所有包含相同轮询循环的回复也是如此

使用事件会更好


查看“getPrice()”函数,找到返回值被更改的位置,并在更改发生时创建一个事件。然后在代码中编写一个处理程序,并在该处理程序中执行轮询循环成功后当前发生的所有操作。

代码的其余部分是什么?我认为不可能用这么少的代码进行重大更改我看不出如何进一步简化此代码。。。只需输入字符串id即可;将其值指定为null是多余的,因为默认情况下它为null。如果您不希望在该循环之外使用id变量,则可以使用yassin的answerpause after action。我不想向服务器发送垃圾邮件和请求。@Simon Eismann:你是对的:不需要递归,但你的最后一种方法是Sitl recursive。我应该睡一觉,去掉剩余的一行:-)你的解决方案缺乏op要求的提前退出功能。@Tagir Valeev:他的变量代码包含中断,用于处理提前退出。这些应该在我的解决方案中仍然有效,对吗?你能帮助我理解你的解决方案吗?何时触发MyTask的执行?hasend()函数是否也必须包含我们要执行的代码?@Simon Eismann:来自corse。看:我的解决方案和你的相同,但是将循环方法(你命名为
loopWithDelay
)引入一个新的抽象,使其更易于重用。然后,您通过一个简单的
Runnable
声明了一段特定的代码,我通过一个更具体的
MyTask
声明了这段代码,因为每次迭代中执行的方法必须返回一个布尔值,以确认循环是否必须结束或继续。是的:
hasend
函数必须包含操作代码和决策代码。有点不相关,但如果numChecks为0,则实际上执行操作一次,并且不睡觉,对吗?谢谢你的解释顺便说一句:-)@Simon Eismann Hum。。。是的,你说得对。但这足以颠倒循环条件的顺序。我会更新的。谢谢。是的,变量代码部分中的内容只是为了说明该区域中的代码在每个块中是不同的,我猜大部分代码与getPrice()更相似。。它发出REST请求并对结果进行处理,更新循环外部存在的一些变量。谢谢,我将花时间来消化它,并看看如何将它应用到我的代码中。虽然在这个方法中只有大约5或6个代码块,但我仍然需要
int x = delayedStream(NUM_CHECKS, DELAY)
             .map(idx -> 1 << (idx+1))
             .filter(val -> val > 25)
             .findFirst().orElse(-1);