2016-07-07 2 views
-1

루프 용으로 중첩 된 guava iterator 또는 java8 foreach (람다 식일 수 있음)를 사용하여 일부 문을 처리하고 long 변수를 반환합니다. 네이티브 java에 내 코드가 있습니다. 내 코드가 효율적이지 않을 수도 있습니다. 새로운 자바 8 foreach 내부 최종 변수를 액세스하는 그물을 통해 읽을 수 없습니다.중첩 된 foreach에 대한 Guava 반복자

Long x = Long.valueOf(0); 
Long y = Long.valueOf(0); 
for(FirstLevel first : Levels) 
{ 
    if(first.getSecondLevels() == null) 
    { 
     x= x + getSomeValue(first); 
    } 
    for (SecondLevel second : first.getSecondLevels()) 
    { 
     y = y + getSomeValue(second); 
    } 
} 
return x + y; 

시도했지만 값을 반환 할 수 없습니다. 도움에 미리 감사드립니다!

+0

그래서 레벨은 루프를 통과하는 횟수를 추적하는 것일뿐입니다. –

+0

그리고 x + = getSomeValue (x) // 같은 것을 시도해보십시오. 그러나 getSomeValue (첫 번째) 여야합니까? –

답변

3

커플 일 :

  1. 물어 하나 같이 "리팩토링"에 접근하기 전에, 정말 강력하게 (내가 여기에 사건입니다 @javalearner을 가정하는) 자바 더 "순수"학습하는 것이 좋습니다. 예를 들어, 당신은 long 리터럴 대신 수동으로 권투 값을 사용할 수 있습니다 어쨌든

    long x = 0L; 
    long y = 0L; 
    

    을 ... 여기에 도움이되지 않습니다 구아바를 사용

  2. -이 그 일의 필수적 방법 이며, 자바 7 + Guava를 사용하면 어색한 익명 클래스 (예 : Function)를 작성해야합니다. 언어 지원 없이는 고통 스럽습니다. 어느 날 나를 데려 오는데 ...
  3. Java 8 및 Streams. 이것은 아마도 최선의 방법 일 것입니다. 그러나 먼저 코드를 수정하고 실제 문제를 정의해야합니다. 예를 들어,이 문 x= x + getSomeValue(x);은 매번 x을 평가하며 FirstLevel을 고려하지 않습니다 (ySecondLevel에 대해서도 마찬가지 임) , 그래서 당신이 정말로 의도 한 바가 x =+ getSomeValue(firstLevel);이라고 가정합니다.

귀하의 문제가 무엇인지 구체적으로 말씀해주십시오.

편집 : 다음과 같이 할 수 스트림 당신의 코드를 사용하여 설명 후

: 모든

final long s = levels.stream() 
     .mapToLong(first -> getSomeValue(first) + getSecondLevelSum(first)) 
     .sum(); 

private long getSecondLevelSum(final FirstLevel first) { 
    return first.getSecondLevels().stream().mapToLong(this::getSomeValue).sum(); 
} 
+0

죄송합니다. 내가 틀렸어. 귀하의 세 번째 요점은 정확합니다. 나는 지금 편집했다. 구아바에서 가능하지 않다면, 그것은 가능한 자바 8 forEach lamda 표현처럼 가능합니까? Atleast 나는 네이티브 forloop 구문을 피할 필요가있다. 귀하의 회신에 감사드립니다. 많이 – javalearner

+0

나는 java8 사용 efficients 될 생각하고 좋아 보인다. 다른 방법이 있습니까? – javalearner

+0

@ javalearner 스트림 버전을 추가했습니다. – Xaerxess

1

첫째,이 :

final long sum = levels.stream() 
     .mapToLong(first -> getSomeValue(first) + first.getSecondLevels().stream().mapToLong(this::getSomeValue).sum()) 
     .sum(); 

또는 일부 도우미 방법

박스형 Long 값을 사용하는 것은 의미가 없으며 박스형 값이 필요한 경우에도를 호출 할 필요가 없습니다, long 프리미티브를 박스형 Long 개체로 변환 할 때 Java가 이미이 작업을 수행합니다. 피가수의 순서에 의존하지 않는 long 값을 추가 이후 추가

는, 어쨌든 마지막에 추가됩니다 조작을 통해 두 변수를 유지하는 이유가 없습니다 :

long result=0; 
for(FirstLevel first: Levels) { 
    result += getSomeValue(first); 
    for(SecondLevel second: first.getSecondLevels()) { 
     result += getSomeValue(second); 
    } 
} 
return result; 

참고 연산자 +=은 여기서 result = result + …과 동일하지만 대상 피연산자의 반복을 피합니다.

하면, Levels 배열 인 경우 또는,

return Levels.stream() 
    .flatMapToLong(first -> LongStream.concat(
     LongStream.of(getSomeValue(first)), 
     first.getSecondLevels().stream().mapToLong(second -> getSomeValue(second)))) 
    .sum(); 

return Levels.stream() 
    .mapToLong(first -> 
     getSomeValue(first) + first.getSecondLevels().stream() 
      .mapToLong(second -> getSomeValue(second)).sum()) 
    .sum(); 

으로 트림 동작과 같은 물품 또는 수 모두 LevelsgetSecondLevels의 결과, 컬렉션 있다고 가정 Levels.stream()Arrays.stream(Levels)으로 대체해야하며 마찬가지로 getSecondLevels()이 배열을 반환하면 first.getSecondLevels().stream()을으로 대체해야합니다.

+0

'LongStream # concat' 및'Stream # flatMapToLong'을 사용한 멋진 트릭! – Xaerxess

+0

@Xaerxess : 예, '평면 맵 (flatMap)'접근법은 터미널 연산에 중요해질 수 있습니다 (합산만큼 중요하지 않음). – Holger