2
我無法用Stream
替換包含遞歸調用的for循環。該代碼是關於在知道該數字的主要因素時生成給定數字的適當除數。該算法取自here,它在圖像中描繪。這是一個部分我的演示目的的代碼,它是可運行:用for循環替換遞歸
public class Demo {
private static void generateDivisorsTraditional(int start, long lastFactor, Multiset<Long> primeFactors, Set<Long> divisors) {
for (int i = start; i < primeFactors.elementSet().size(); i++) {
long prime = Iterables.get(primeFactors.elementSet(), i);
int count = primeFactors.count(prime);
++start;
for (int c = 0; c <= count; c++) {
long factor = ArithmeticUtils.pow(prime, c);
divisors.add(lastFactor * factor);
generateDivisorsTraditional(start, lastFactor * factor, primeFactors, divisors);
}
}
}
private static void generateDivisorsStream(int start, long lastFactor, Multiset<Long> primeFactors, Set<Long> divisors) {
IntStream.range(start, primeFactors.elementSet().size())
.forEach((int i) -> {
long prime = Iterables.get(primeFactors.elementSet(), i);
int count = primeFactors.count(prime);
final int begin = start + 1;
IntStream.range(0, count + 1)
.forEach((int c) -> {
long factor = ArithmeticUtils.pow(prime, c);
divisors.add(lastFactor * factor);
generateDivisorsStream(begin, lastFactor * factor, primeFactors, divisors);
});
});
}
private static void testTraditional(Multiset<Long> primeFactors) {
Set<Long> divisors = new TreeSet<>();
generateDivisorsTraditional(0, 1, primeFactors, divisors);
System.out.println("Traditional=> " + divisors);
}
private static void testStream(Multiset<Long> primeFactors) {
Set<Long> divisors = new TreeSet<>();
generateDivisorsStream(0, 1, primeFactors, divisors);
System.out.println("Stream=> " + divisors);
}
private static void testStream1(Multiset<Long> primeFactors) {
Set<Long> divisors = new TreeSet<>();
new Inner().generateDivisorsStream(1, primeFactors, divisors);
System.out.println("Stream1=> " + divisors);
}
public static void main(String[] args) {
System.out.println("Test number: 10");
Multiset<Long> primeFactors = TreeMultiset.create();
primeFactors.add(2L);
primeFactors.add(5L);
testTraditional(primeFactors);
testStream(primeFactors);
testStream1(primeFactors);
System.out.println();
System.out.println("Test number: 90");
primeFactors = TreeMultiset.create();
primeFactors.add(2L);
primeFactors.add(3L);
primeFactors.add(3L);
primeFactors.add(5L);
testTraditional(primeFactors);
testStream(primeFactors);
testStream1(primeFactors);
}
private static class Inner {
private int start = 0;
private void generateDivisorsStream(long lastFactor, Multiset<Long> primeFactors, Set<Long> divisors) {
IntStream.range(start, primeFactors.elementSet().size())
.forEach((int i) -> {
long prime = Iterables.get(primeFactors.elementSet(), i);
int count = primeFactors.count(prime);
++start;
IntStream.range(0, count + 1)
.forEach((int c) -> {
long factor = ArithmeticUtils.pow(prime, c);
divisors.add(lastFactor * factor);
generateDivisorsStream(lastFactor * factor, primeFactors, divisors);
});
});
}
}
}
輸出它發生是:
Test number: 10
Traditional=> [1, 2, 5, 10]
Stream=> [1, 2, 5, 10, 25]
Stream1=> [1, 2, 5]
Test number: 90
Traditional=> [1, 2, 3, 5, 6, 9, 10, 15, 18, 30, 45, 90]
Stream=> [1, 2, 3, 5, 6, 9, 10, 15, 18, 25, 27, 30, 45, 50, 75, 81, 90, 125, 135, 225, 405]
Stream1=> [1, 2, 3, 5, 9]
正如其名稱所暗示的方法generateDivisorsTraditional
使用傳統的for循環和內我有一個遞歸調用相同的方法。方法generateDivisorsStream
使用IntStream.range()
來模擬for循環。
我懷疑++start;
和final int begin = start + 1;
的generateDivisorsTraditional
和generateDivisorsStream
分別有所不同。我也嘗試使用final int begin = start + 1;
而不是++start;
在generateDivisorsTraditional
,並且發現它已經開始產生錯誤的結果。我在內部類Inner
中也有另一個變體,它也會產生錯誤的輸出。
我想知道爲什麼這不是表現它的行爲方式?我犯了什麼錯誤?
是不是覺得應該是'我+ 1'由我應更換'start'?我用'i'檢查過,它不可避免地給了我'StackOverflowError'。 –
@TapasBose你是對的,'開始' - >'i + 1',編輯過 –