2014-10-20 3 views
0

У меня есть обучающая java 8 самая сложная вещь, с которой мне приходится сталкиваться: Parallel reduction. вот код с примера пользователя @Stuart Marks, с которым я изучаю.Java8 поток параллельный уменьшить аккумулятор BiFunction

class ImmutableAverager 
{ 
    private final int total; 
    private final int count; 
    public ImmutableAverager(){this.total = 0;this.count = 0;} 
    public ImmutableAverager(int total, int count) 
    { 
     this.total = total; 
     this.count = count; 
    } 
    public double average(){return count > 0 ? ((double) total)/count : 0;} 
    public ImmutableAverager accept(final int i) 
    { 
     return new ImmutableAverager(total + i, count + 1); 
    } 
    public ImmutableAverager combine(final ImmutableAverager other) 
    { 
     return new ImmutableAverager(total + other.total, count + other.count); 
    } 

вызов

public static void main(String[] args)  
{ 
     System.out.println(Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 
     .parallel() 
     .reduce(new ImmutableAverager(), 
       ImmutableAverager::accept, 
       ImmutableAverager::combine) 
     .average());  
} 

это производят правильные результаты, но позже я проверил подпись метода снижения

<U> U reduce(U identity, 
      BiFunction<U, ? super T, U> accumulator, 
      BinaryOperator<U> combiner); 

я понял бы ясно, если код будет что-то вроде

.reduce(new ImmutableAverager(),(a,b)->a.accept(b),(a,b)->a.combine(b)) 

я не понимаю, как

ImmutableAverager::accept 

может конвертировать в BiFunction

мое понимание ..

это

ImmutableAverager::accept 

это превратить его в нечто вроде

(ImmutableAverage a)->a.accept();//but this is a function with 1 parameter not with 2 parameters. 

и

ImmutableAverager::merge 

может конвертировать в BinaryOperator мой друг @Stuart Маркс говорит

методы совпадают с аргументами функции, чтобы уменьшить таким образом мы можем использовать ссылки на метод.

извините, если вопрос прост, но любая помощь очень ценят ..

наилучшими пожеланиями из Венесуэлы

+0

Hi. К счастью, я оказался в сети в тот момент, когда вы задали этот вопрос. :-) –

ответ

2

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

Давайте рассмотрим второй аргумент reduce(). Он хочет

BiFunction<U, ? super T, U> accumulator 

и поэтому подпись абстрактном метода:

U apply(U, T) 

(подстановочные Опущенные для краткости). Пример использовал ссылки на метод ImmutableAverager::accept и его подпись:

ImmutableAverager accept(int i) 

Это выглядит, как это не работает, потому что BiFunction требует два аргумента, в то время как метод accept занимает только один.Но обратите внимание, что метод accept представляет собой метод экземпляра класса ImmutableAverager, поэтому он неявно также принимает «приемник», то есть объект, на который вызывается этот метод. Обычный вызов этого метода может выглядеть следующим образом:

newAverager = oldAverager.accept(i); 

Так на самом деле, метод accept фактически принимает два аргументов, даже если он не похож на него. Первый - приемник, который имеет тип ImmutableAverager, а второй - типа int. Синтаксис вызова метода делает его похожим на что-то особенное в ресивере, но на самом деле его нет. Это как если бы это был статический метод как это:

newAverager = accept(oldAverager, i); 

Теперь давайте посмотрим, как это работает с reduce вызова. Код, о котором идет речь,

reduce(..., ImmutableAverager::accept, ...) 

Я только показываю здесь второй аргумент. Это должно быть BiFunction, которое принимает аргументы U и T и возвращает U, как показано выше. Если вы посмотрите на метод accept и рассматриваете приемник не как нечто особенное, а как обычный аргумент, он принимает аргумент типа ImmutableAverager и аргумент типа int и возвращает ImmutableAverager. Таким образом, U считается ImmutableAverager и T Предполагается, что: Integer (в коробке от int), и здесь используется ссылка на метод.

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

+0

да очень повезло .... большое спасибо Стюарту и богу Блаженству .... – chiperortiz

Смежные вопросы