Как правильно написать это с потоками?

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

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

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


person Noctis Skytower    schedule 03.06.2016    source источник
comment
Какова цель именованного блока error?   -  person Michael    schedule 03.06.2016
comment
Когда выполняется break error;, это означает, что текущее значение position нельзя использовать, поскольку оно находится в пределах минимального поля какой-либо другой звезды. Если break error; не выполняется, то предполагается, что throw new XStarField.Found(); будет выполнено и перехвачено обработчиком события (исключения). В этот момент известно, что значение position приемлемо.   -  person Noctis Skytower    schedule 03.06.2016
comment
Хорошо, имеет смысл! Хотя это и не имеет прямого отношения, ответы в вопросе, который я опубликовал ранее, помогли сбросить немного света в этой ситуации   -  person Michael    schedule 03.06.2016
comment
Спасибо, но ответы не объясняют правильный способ создания и обработки исключений (событий) и, похоже, не предлагают решения для реализации сложной логики управления.   -  person Noctis Skytower    schedule 03.06.2016
comment
Ждать. Вы пытались использовать исключения для потока управления в Java, где это противоречит культуре языка, но не в Python, одном из немногих языков, культура которых считает это совершенно нормальным?   -  person user2357112 supports Monica    schedule 03.06.2016
comment
Мне кажется, что это должно генерировать поток случайных векторов -> filter из тех, которые не соответствуют маржинальным требованиям -> findFirst.   -  person user2357112 supports Monica    schedule 03.06.2016
comment
И в моем коде, и в комментариях исключение постоянно упоминается как событие. В целях обсуждения именно так это следует рассматривать в данном контексте. Тем, кто не может приспособиться к такой странной парадигме, вероятно, следует избегать этого вопроса.   -  person Noctis Skytower    schedule 03.06.2016
comment
Исключения не являются событиями - во всяком случае, не в Java. Если вы хотите рассматривать это как событие, я бы посоветовал вам использовать обычную парадигму: создать прослушиватель событий и вызывать его с вашим событием вместо того, чтобы генерировать исключение. Хотя я подозреваю, что этот код будет делать то, что вы хотите, если ваше исключение будет непроверенным...   -  person dcsohl    schedule 03.06.2016
comment
Да, ответ на мой вопрос заключался в том, чтобы XStarField.Found наследовать от RuntimeException вместо Exception. Вы правы в том, что мое использование исключения как события является довольно необычной парадигмой, но искажение моих мыслей привело к полезному рабочему решению.   -  person Noctis Skytower    schedule 03.06.2016
comment
@ user2357112 PEP 8 говорит: «Здесь применяются соглашения об именах классов, хотя вы должны добавить суффикс «Ошибка» к своим классам исключений, если исключение является ошибкой. Исключения без ошибок, которые используются для нелокального управления потоком или других форм сигнализации, не нуждаются в специальном суффиксе.   -  person Noctis Skytower    schedule 08.07.2016


Ответы (1)


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

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));
    });
});
person Noctis Skytower    schedule 27.09.2016