Идентичность для бинарного оператора - PullRequest
0 голосов
/ 12 сентября 2018

Я вижу в Java8 в интерфейсе UnaryOperator следующий фрагмент кода, который ничего не делает с параметром и возвращает то же значение.

static <T> UnaryOperator<T> identity() {
    return t -> t;
}

Есть ли что-нибудь для BinaryOperator, который принимает два параметра samekind и возвращает одно значение

static <T> BinaryOperator<T> identity() {
    return (t,t) -> t;
}

почему я задаю этот вопрос для требования ниже,

List<String> list = Arrays.asList("Abcd","Abcd");
Map<String,Integer> map = list.stream().collect(Collectors.toMap(str->str, 
str->(Integer)str.length(),(t1,t2)->t1));
System.out.println(map.size());

в приведенном выше коде я не хочу ничего делать для двух значений одного и того же ключа, я просто хотел вернуть одно значение, потому что в моем случае наверняка значения будут одинаковыми. Поскольку я не использую ошибку выброса сонара значения t2, я выясняю, есть ли что-то вроде UnaryOperator.identity () для BinaryOpertor также в java8

Ответы [ 3 ]

0 голосов
/ 12 сентября 2018

Ваш код может быть улучшен как

List<String> list = Arrays.asList("Abcd", "Abcd");
Map<String, Integer> map = list.stream()
            .collect(Collectors.toMap(Function.identity(), String::length, (a, b) -> a));
System.out.println(map.size());

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

private static <T> BinaryOperator<T> any() {
    return Math.random() < 0.5 ? ((x, y) -> x) : ((x, y) -> y);
}

и затем в вашем коде используйте его как

Map<String, Integer> map = list.stream()
            .collect(Collectors.toMap(Function.identity(), String::length, any()));

Благодаря предложениям Хольгера, Юджина и Федерико, есть и другие эффективные реализации метода any, которые могут фактически включать использование:

private static <T> BinaryOperator<T> any() {
    // suggested by Holger
    return ThreadLocalRandom.current().nextBoolean() ? ((x, y) -> x) : ((x, y) -> y);
    // suggested by Eugene
    long nt = System.nanoTime(); 
    ((nt >>> 32) ^ nt) > 0 ? ((x, y) -> x) : ((x, y) -> y);
}
0 голосов
/ 12 сентября 2018

Ваш вопрос на самом деле не имеет смысла.Если бы вы вставили предложенный метод BinaryOperator.identity в IDE, вы бы сразу увидели, что он пожалуется на то, что идентификатор t объявляется дважды.

Чтобы это исправить, нам нужны разные идентификаторы для каждогопараметр:

return (t, u) -> t;

Теперь мы можем ясно видеть, что это не функция identity .Это метод, который принимает два аргумента и возвращает первый.Поэтому лучшим названием для этого было бы что-то вроде getFirst.

Чтобы ответить на ваш вопрос о том, есть ли что-то подобное в JDK: нет .Использование функции тождественности является распространенным случаем, поэтому определение метода для этого полезно.Произвольный возврат первого аргумента из двух не является распространенным случаем, и не имеет смысла иметь метод для этого.

0 голосов
/ 12 сентября 2018

T означает, что они имеют одинаковые типы , а не одинаковые значения , что само по себе не является идентичностью.

Это просто означает, что BinaryOperator будет использоваться для одних и тех же типов, но предоставляя identity для различных значений ... это звучит как foldLeft или foldRight или foldLeftIdentity/foldRightIdentity, чтоЯва не имеет.

...