Параллельный поток, не позволяющий мне исключать [duplicate]

Для внутреннего соединения во всех столбцах вы также можете использовать fintersect из data.table -пакет или intersect из dplyr -пакета в качестве альтернатив merge без указания by -колонков. это даст строки, которые равны между двумя кадрами данных:

merge(df1, df2)
#   V1 V2
# 1  B  2
# 2  C  3
dplyr::intersect(df1, df2)
#   V1 V2
# 1  B  2
# 2  C  3
data.table::fintersect(setDT(df1), setDT(df2))
#    V1 V2
# 1:  B  2
# 2:  C  3

Пример данных:

df1 <- data.frame(V1 = LETTERS[1:4], V2 = 1:4)
df2 <- data.frame(V1 = LETTERS[2:3], V2 = 2:3)
105
задан Luiggi Mendoza 8 May 2014 в 21:31
поделиться

6 ответов

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

Нормальная оберточная идиома - это что-то вроде:

private void safeFoo(final A a) {
    try {
        a.foo();
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}

(исключение Supertype Exception только , используемый в качестве примера, никогда не пытайтесь его поймать)

Затем вы можете вызвать его с помощью: as.forEach(this::safeFoo).

96
ответ дан skiwi 21 August 2018 в 18:37
поделиться
  • 1
    Если вы хотите, чтобы это был метод оболочки, я бы объявил его статическим. Он ничего не использует от «этого». – aalku 13 May 2014 в 16:18
  • 2
    Печально, что мы должны это сделать, а не использовать наши собственные исключения ... о, Java, он дает, а затем отнимает – Erich 27 February 2015 в 22:29
  • 3
    @kdubb Посмотрите на ответ marcg: stackoverflow.com/a/27661475/363573 . Его вспомогательный класс UtilException обеспечивает некоторую работу ... – Stephan 13 June 2015 в 10:43
  • 4
    @Stephan Этот ответ был удален, но он по-прежнему доступен здесь: stackoverflow.com/a/27661562/309308 – Michael Mrozek 14 January 2016 в 05:31
  • 5
    Это мгновенно завершит проверку кода в моей компании: нам не разрешено исключать исключенные исключения. – Stelios Adamantidis 28 May 2018 в 12:13

Вы можете обернуть и развернуть исключения таким образом.

class A {
    void foo() throws Exception {
        throw new Exception();
    }
};

interface Task {
    void run() throws Exception;
}

static class TaskException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    public TaskException(Exception e) {
        super(e);
    }
}

void bar() throws Exception {
      Stream<A> as = Stream.generate(()->new A());
      try {
        as.forEach(a -> wrapException(() -> a.foo())); // or a::foo instead of () -> a.foo()
    } catch (TaskException e) {
        throw (Exception)e.getCause();
    }
}

static void wrapException(Task task) {
    try {
        task.run();
    } catch (Exception e) {
        throw new TaskException(e);
    }
}
7
ответ дан aalku 21 August 2018 в 18:37
поделиться

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

Самый элегантный способ, на мой взгляд, вы можете найти здесь, здесь Миша . Агрегатные исключения времени выполнения в Java 8 потоках , просто выполнив действия в «фьючерсах». Таким образом, вы можете запускать все рабочие части и собирать неработающие Исключения как один. В противном случае вы можете собрать их все в списке и обработать их позже.

Аналогичный подход исходит из Benji Weber . Он предлагает создать собственный тип для сбора рабочих и нерабочих частей.

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

Если вам не нравится какой-либо из этих способов, рассмотрите возможность использования (в зависимости от Исходного Исключения) как минимум собственного исключения.

13
ответ дан Community 21 August 2018 в 18:37
поделиться
  • 1
    К сожалению, спасибо Тагиру Валееву, да, вы правы. Я обновил ответ, чтобы включить трюк , чтобы превратить поток в итератор. – avandeursen 19 September 2015 в 15:47
  • 2
    Это должно быть отмечено как правильный ответ. +. Но я не могу сказать, что это хороший пост. Вы должны это тщательно продумать. Как может помочь собственное исключение? Каковы произошедшие исключения? Почему ты не привел здесь разные варианты? Наличие всего примера кода в ссылках считается даже запрещенным стилем почты здесь на SO. Ваш текст выглядит скорее как куча комментариев. – Gangnus 14 February 2017 в 09:57
  • 3
    Вы должны быть в состоянии выбрать, на каком уровне вы хотите их поймать, и потоки бесполезны с этим. API потока должен позволять вам переносить исключение до окончательной операции (например, собирать) и обрабатываться там с помощью обработчика или иначе бросаться. stream.map(Streams.passException(x->mightThrowException(x))).catch(e->whatToDo(e)).collect(...). Это shodud ожидает исключения и позволяет вам обращаться с ними, как фьючерсы. – aalku 18 April 2018 в 16:47

Я предлагаю использовать класс Google Guava Throwables

распространять (Throwable throwable)

Распространяет throwable as-is, если это экземпляр из RuntimeException или Error, или в качестве последнего средства, обертывает его в RuntimeException и затем распространяется. **

void bar() {
    Stream<A> as = ...
    as.forEach(a -> {
        try {
            a.foo()
        } catch(Exception e) {
            throw Throwables.propagate(e);
        }
    });
}
9
ответ дан fbokovikov 21 August 2018 в 18:37
поделиться

Более читаемый способ:

class A {
  void foo() throws MyException() {
    ...
  }
}

Просто спрячьте его в RuntimeException, чтобы пройти его forEach()

  void bar() throws MyException {
      Stream<A> as = ...
      try {
          as.forEach(a -> {
              try {
                  a.foo();
              } catch(MyException e) {
                  throw new RuntimeException(e);
              }
          });
      } catch(RuntimeException e) {
          throw (MyException) e.getCause();
      }
  }

Хотя на данный момент я не буду держитесь против кого-то, если они говорят, что пропускают потоки и идут с циклом for, если:

  • вы не создаете свой поток, используя Collection.stream(), т. е. не прямолинейный перевод в цикл for.
  • вы пытаетесь использовать parallelstream()
1
ответ дан Kashyap 21 August 2018 в 18:37
поделиться

Возможно, вы захотите выполнить одно из следующих действий:

  • распространить проверенное исключение,
  • обернуть его и развернуть исключенное исключение или
  • catch распространение исключений и остановок.

Несколько библиотек позволяют делать это легко. Пример ниже написан с использованием библиотеки NoException .

// Propagate checked exception
as.forEach(Exceptions.sneak().consumer(A::foo));

// Wrap and propagate unchecked exception
as.forEach(Exceptions.wrap().consumer(A::foo));
as.forEach(Exceptions.wrap(MyUncheckedException::new).consumer(A::foo));

// Catch the exception and stop propagation (using logging handler for example)
as.forEach(Exceptions.log().consumer(Exceptions.sneak().consumer(A::foo)));
4
ответ дан Robert Važan 21 August 2018 в 18:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: