2016-06-03 2 views
0

Следующий код должен выполнить то, что требуется, если обработка исключений работает, как ожидалось:Каков правильный способ написать это потоками?

XVector position = new XVector(); 
IntStream.range(0, desired_star_count).forEach(a -> { 
    // Try to find a position outside the margin of other stars. 
    try 
    { 
     IntStream.range(0, XStarField.patience).forEach(b -> { 
      position.random(size); 
      error: 
      { 
       for (XVector point : this.positions) 
        if (position.sub(point).get_magnitude() < min_star_margin) 
         break error; 
       throw new XStarField.Found(); 
      } 
     }); 
    } 
    catch (XStarField.Found event) 
    { 
     this.positions.add(position.copy()); 
     this.colors.add(Math.random() < 0.5 ? XColor.RED : XColor.BLUE); 
    } 
}); 

К сожалению, следующие две ошибки генерируются:

Error:(33, 25) java: unreported exception XStarField.Found; must be caught or declared to be thrown 
Error:(37, 13) java: exception XStarField.Found is never thrown in body of corresponding try statement 

Если бы я был написать один и тот же код Python, это, вероятно, получится так:

position = XVector() 
for a in range(desired_star_count): 
    for b in range(self.patience): 
     position.random(size) 
     for point in self.positions: 
      if abs(position - point) < min_star_margin: 
       break 
     else: 
      self.position.append(position.copy()) 
      self.colors.append(XColor.RED if random.random() < 0.5 else XColor.BLUE) 
      break 

Это было бы просто написать без использования потоков, но я считаю, что это научное обучение, чтобы лучше понять их. Есть ли способ написать код для замены циклов подсчета и использовать потоки на своем месте, как было предпринято?

+0

Какова цель именованного блока 'error'? – Michael

+0

Когда выполняется 'break error;', это означает, что текущее значение 'position' не может быть использовано, поскольку оно находится в пределах минимального поля некоторой другой звезды. Если 'break error',' не выполняется, тогда 'throw new XStarField.Found();' предполагается выполнить и поймать обработчик события (исключения). В этот момент известно, что значение «позиция» является приемлемым. –

+0

OK, имеет смысл! Хотя это и не было напрямую связано, ответы в [вопросе] (http://stackoverflow.com/questions/33590916/idiomatic-way-of-traversing-image-functionally) Я опубликовал ранее мою помощь, пролил свет в этой ситуации – Michael

ответ

0

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

XVector position = new XVector(); 
IntStream.range(0, DESIRED_STAR_COUNT).forEach(a -> { 
    // Try to find a position outside the margin of other stars. 
    IntStream.range(0, PATIENCE).filter(b -> { 
     position.random(size); 
     return !this.positions.stream().anyMatch(point -> position.sub(point).getMagnitude() < MIN_STAR_MARGIN); 
    }).findFirst().ifPresent(b -> { 
     this.positions.add(position.copy()); 
     this.colors.add((XColor) XRandom.sChoice(RED_STAR, BLUE_STAR)); 
    }); 
});