2016-07-07 5 views
-1

ループ用にネストされたguava iteratorまたはjava8 foreach(lambda式かもしれません)を使用して、いくつかの文を処理してlong変数を返したいとします。ここではネイティブJavaで私のコードです。私のコードが効率的ではないかもしれないことをご了承ください。私は新しい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ケースであると仮定)より「純粋な」は、Javaを学ぶお勧めします。これはそれをやっての不可欠な方法である、とJavaで - とにかく...グァバを使用して

  2. はここに助けにはなりません

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

    :たとえば、あなたの代わりに値を手動でボクシングのlongリテラルを使用することができます7 + Guavaを使用すると、厄介な匿名クラス(すなわち、Function)を記述する必要があります。それは私にもたらす...

  3. Java 8とストリーム。これはたぶん最善の方法ですが、コードを修正して実際の問題を定義する必要があります。たとえば、この文x= x + getSomeValue(x);は毎回xを評価し、FirstLevelを考慮に入れません(ySecondLevelについても同じです)あなたが本当に意味していたのはx =+ getSomeValue(firstLevel);だと思います。

あなたの問題が本当に何であるかを具体的に説明してください。

EDIT:あなたの明確化の後

、あなたのコードは次のようになりますストリームを使用して:

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

またはいくつかのヘルパーメソッドを持つ:すべての

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

申し訳ありません。私は間違っていた。あなたの3番目のポイントは正しいです。私は今編集しました。グアバでは不可能な場合は、lamda式のようにjava 8 forEachで可能ですか?少なくとも私はforloopネイティブの構文を避ける必要があります。お返事をありがとうございます。非常に高く評価しました – javalearner

+0

私はjava8を使っていると効率が良くなりました。他の方法はありますか? – javalearner

+0

@ javalearnerストリームバージョンを追加しました。 – Xaerxess

1

まず、そこに箱入りのLongの値を使用する意味がなく、ボックス化された値が必要な場合でも、を呼び出す必要はありませんの場合、longプリミティブをボックス化Longオブジェクトに変換するときに、Javaはすでにこれを行います。さらに

long値を追加すると、加数の順序に依存しないため、とにかく最後にそれらを追加しますと、操作全体の2つの変数を維持する理由がない:

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

。なお、演算子+=result = result + …と同じですが、ターゲットオペランドの繰り返しは避けてください。双方、LevelsgetSecondLevelsの結果は、Levelsが配列である場合、あなたは、

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

、あるいは

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

としてストリーム動作と同じように書くことができるコレクションであると仮定すると

Levels.stream()Arrays.stream(Levels)に置き換え、同様にgetSecondLevels()が配列を返す場合は、first.getSecondLevels().stream()をに置き換える必要があります

+0

'LongStream#concat'と' Stream#flatMapToLong'の素晴らしいトリック! – Xaerxess

+0

@Xaerxess:ええ、 'flatMap'アプローチは、ターミナル操作では重要でなくても、要約と同じくらい重要になります。 – Holger

関連する問題