Есть ли способ вернуть значение из цикла и продолжить с того места, где я остановился?

Есть ли способ вернуть значение из loop и продолжить с того места, где я остановился?

В следующем фрагменте я хочу вернуть текущее значение currVm. Но я не могу этого сделать.

В самом внутреннем цикле фрагмента:

while(c <= currVm) {
   allocatedVm(currVm);
   c++;
}

вызывается функция с именем allocatedVm. Я хочу вернуть значение currVm и начать снова с того места, где я остановился. Есть ли выход?

@Override
public int getNextAvailableVm() {
    Set<String> dataCenters = confMap.keySet();
    for (String dataCenter : dataCenters) {
        LinkedList<DepConfAttr> list = confMap.get(dataCenter);
        Collections.sort(list, new MemoryComparator());
        int size = list.size() - 1;
        int count = 0;
        while(size >= 0) {
            DepConfAttr dca = (DepConfAttr)list.get(count);
            int currVm = dca.getVmCount();
            int c = 0;
            while(c <= currVm) {
                allocatedVm(currVm); // RETURN currVm
                c++;
            }
            count++;
            size--;
        }
    }        
}

person saplingPro    schedule 31.08.2013    source источник
comment
Трудно догадаться, о чем вы говорите, так как вы не показали нам метод выделенного Vm. И откуда вы возвращаете это значение, и какую часть вы хотите возобновить?   -  person Rohit Jain    schedule 31.08.2013
comment
@RohitJain, зачем тебе метод allocatedVm?   -  person saplingPro    schedule 31.08.2013
comment
@RohitJain, ОП ожидает что-то вроде LazySeq (Java 8), Stream (scala)   -  person Prince John Wesley    schedule 31.08.2013
comment
@RohitJain, и я хочу вернуть значение, как только вызову allocatedVM   -  person saplingPro    schedule 31.08.2013


Ответы (3)


Лучшим подходом, вероятно, было бы написать метод, возвращающий Iterable<Integer>. В Java это не так просто, как в языках, поддерживающих функции генератора (например, C# и Python), но все же возможно. Если код короткий, вы можете обойтись парой (вложенных) анонимных внутренних классов:

public Iterable<Integer> foo() {
    return new Iterable<Integer>() {
        @Override public Iterator<Integer> iterator() {
            return new Iterator<Integer>() {
                // Implement hasNext, next and remove here
            };
        }
    };
}

В вашем случае у меня возникнет соблазн разбить его на отдельный неанонимный класс, просто для простоты.

В любом случае, смысл использования Iterable в том, что Iterator естественным образом имеет состояние — в основном это его цель. Так что это хорошо подходит для ваших требований.

Другой, более простой подход, состоит в том, чтобы вернуть все элементы за один раз и заставить вызывающую программу выполнять выделение по требованию. Очевидно, что это не работает, если может быть огромное количество элементов, но это было бы легче понять.

person Jon Skeet    schedule 31.08.2013
comment
Я не понял. Что я реализую внутри return new Iterator<?> {..} - person saplingPro; 31.08.2013
comment
@saplingPro: вам нужно реализовать интерфейс Iterator - методы hasNext, next и remove. (Возможно, вы захотите просто создать исключение из remove.) Вероятно, вам потребуется превратить все ваши локальные переменные в переменные экземпляра в итераторе. Это не будет приятным кодом, но в основном такова природа необходимости сохранять состояние между вызовами. - person Jon Skeet; 31.08.2013
comment
@saplingPro: см. мой отредактированный ответ для другой альтернативы (внизу) - нам понадобится больше контекста, чтобы узнать, подходит ли это. - person Jon Skeet; 31.08.2013
comment
@saplingPro: Нет, боюсь, что нет. На самом деле у нас недостаточно контекста, чтобы знать наиболее подходящий вариант действий (итератор или возврат всей коллекции), и у меня нет времени просто преобразовать ваш код в итератор прямо сейчас. Вы должны попробовать это сами (сначала изучите интерфейсы Iterable и Iterator), а затем, если у вас возникнут проблемы, задайте конкретные вопросы по вашему коду. - person Jon Skeet; 31.08.2013

не уверен, что понимаю, что вам нужно, но:

если вы хотите уведомить вызывающую сторону метода о том, что у вас есть значение во время выполнения метода, но пока не хотите выходить из метода, вы можете использовать прослушиватели.

просто создайте интерфейс в качестве параметра вашей функции и создайте внутри функцию, которая будет иметь объект в качестве параметра.

пример:

interface IGotValueListener 
  {
  public void onGotValue(MyClass obj); 
  }

public int getNextAvailableVm(IGotValueListener listener)
  {
  ...
  if(listener!=null)
    listener.onGotValue(...);
  }

теперь для вызова метода вы делаете:

int finalResult=getNextAvailableVm(new IGotValueListener ()
  {
  ... //implement onGotValue
  };
person android developer    schedule 31.08.2013

Вы можете вернуться из любого места в вашем методе, просто вставив ключевое слово return. Если вы хотите добавить функциональность для возобновления вашего метода из разных мест, вам нужно учитывать ваш метод таким образом. Вы можете использовать операторы labels и if, установить некоторые статические переменные, чтобы отметить последнее место выполнения. Если ваше приложение не является многопоточным, вам не нужно беспокоиться об использовании синхронизации статических переменных. Кроме того, если ваш метод слишком велик и становится трудно следовать/читать, подумайте о том, чтобы разбить его на более мелкие.

person Juned Ahsan    schedule 31.08.2013
comment
вы можете помочь мне с этим кодом? Я хочу вернуть currVm, как только позвоню allocatedVm(...) - person saplingPro; 31.08.2013
comment
@saplingPro поместил оператор возврата после выделенного Vm (...). - person Juned Ahsan; 31.08.2013