2016-12-15 52 views
1

我對一個似乎無法處理它的局部變量和lambda函數有個奇怪的問題。我不斷收到錯誤消息「在一個封閉的範圍內定義局部變量ACC必須是最後的或有效的最終」Java中局部變量+ lambda函數的錯誤

我的代碼如下所示:

Accumulator acc = new Accumulator(0, 0); 
stream.reduce(0, (sum, value) -> { 
    acc = new Accumulator(sum + value, acc.getB()+1); 
    return sum + value; 
}); 

因此,大家可以看到,我試圖減少整數流並保留2個值,而不僅僅是減少進程中的一個。我試圖將這些值保存在小幫手類Accumulator中,其中有final int afinal int b來存儲這些值。但是,它好像stream.reduce無法達到acc

在我的程序的其他部分,包括其他lambda函數,類似的代碼結構工作正常(聲明局部變量並在lambda函數內改變它們),所以我不知道該怎麼做。

實施例(該stream被初始化當然):

ArrayList<StudentRecord> studentList = new ArrayList<StudentRecord>(); 
stream.forEach(student -> { 
    studentList.add(student); 
}); 

幫助將理解的, 問候

+0

錯誤信息告訴你到底發生了什麼問題:'acc'沒有聲明爲'final'。問題是什麼? –

+0

[請在搜索前搜索](/ search?q =%5Bjava%5D + local + variable + defined + in + an + enclosing + scope + must + be + final + or + effective + final),more [ ](/幫助/搜索)。 –

+0

如果您發佈了其他代碼,那麼我們可以告訴你有什麼不同。否則,我們在這裏沒有任何事情要做。 – HopefullyHelpful

回答

2

正如評論中所述,您不能在lambda表達式中分配一個局部變量。但是,有幾種方法可以調用reduce方法來生成您想要的輸出。

例如:

Stream<Integer> stream = Stream.of (1,2,3,4,5); 
Accumulator result = 
    stream.reduce(new Accumulator(0,0), // initial value 
        (acc, i) -> {acc.a += i;acc.b++; return acc;}, // add current value to 
                   // the accumulator 
        (acc1, acc2) -> new Accumulator (acc1.a+acc2.a,acc1.b+acc2.b)); // combine two accumulators 
System.out.println ("sum = " + result.a); 
System.out.println ("count = " + result.b); 

這產生僅一個Accumulator實例(除非你Stream平行)。輸出Accumulator將包含acc.a中的總和以及acc.b中的元素數。

輸出:

sum = 15 
count = 5 

我假設這是僅用於教育目的。如果不是,則使用IntStreamsummaryStatistics()來計算總和,元素數量和其他屬性(最小值,最大值和平均值)會更有意義。

+0

是的,這是爲了教育目的,我們甚至沒有被要求在這個過程中使用像Accumulator這樣的課程。我只是想實現它,卡住了,想知道爲什麼。感謝您的片段,它非常幫助我! – Daniel

1

的變量不能被聲明爲最終,但它不能被重新分配,所以它實際上是最終的。 在代碼的第3行中,重新分配變量。這不可能。

如果你說,你已經做了類似的事情已經成功的其他代碼:我認爲這是不可能的。可能你改變了變量引用的對象,但不是變量本身。

+0

謝謝,那就是它。我並不完全確定「有效的最終」是什麼意思。 – Daniel

+0

雖然你的答案可能是正確的,但是在沒有參考Java規範或文檔的情況下做出這種聲明是不受歡迎的,因爲你正在描述規範的細節,這在未來可能會發生變化。否則,請包括您正在使用的當前Java版本,您的行爲被觀察到。或者首先確保你的聲明在不同的例子中成立,並將它們包含在答案中。我知道,對於下一個java版本,它被計劃改變,所以這個答案會混淆未來的訪問者。 – HopefullyHelpful

+0

@HopefullyHelpful由於使用lamdas的問題我們當然在談論Java 8.事實上,在Java 8之前,匿名內部類只能使用顯式聲明爲final的變量(在Java 7或之前並沒有「有效最終」的概念到Java 7)。 –