2017-02-07 4 views
0

実際にはこれはLeetCode#56で、結果を計算するためにTreeMapを使用しています。Java Map.Entryを非最終変数でストリームに転送

コードは次のとおりです。

public List<Interval> merge(List<Interval> intervals) { 
    Map<Integer, Integer> tMap = intervals.stream().collect(Collectors.toMap(i -> i.start, i -> i.end, (i, j) -> i > j ? i : j)); 
    Map<Integer, Integer> map = new TreeMap<Integer, Integer> (tMap); 
    List<Interval> res = new ArrayList<Interval>(); 
    int left = Integer.MAX_VALUE, right = Integer.MAX_VALUE, tmpLeft = -1, tmpRight = -1; 
    Set<Map.Entry<Integer, Integer>> set = map.entrySet(); 
    for (Map.Entry<Integer, Integer> entry : set) 
    { 
     if (Integer.MAX_VALUE == left && Integer.MAX_VALUE == right) 
     { 
      left = entry.getKey(); 
      right = entry.getValue(); 
     } 
     else 
     { 
      tmpLeft = entry.getKey(); 
      tmpRight = entry.getValue(); 
      if(right < tmpLeft) 
      { 
       res.add(new Interval(left, right)); 
       left = tmpLeft; 
      } 
      right = right > tmpRight ? right : tmpRight; 
     } 
    } 
    if (Integer.MAX_VALUE != left && Integer.MAX_VALUE != right) 
     res.add(new Interval(left, right)); 
    return res; 
} 

それは動作しますが、ストリームでこれを行うための方法があるならば、私は思ったんだけど。

  1. Can TreeMap Map<Integer, Integer> map = new TreeMap<Integer, Integer> (tMap);はストリームで直接生成されますか?

  2. 私はSet<Map.Entry<Integer, Integer>> setと以下のループを持っていますが、それをストリームで行う方法はありますか?

+2

'(i、j) - > i> j? i:j'は 'Math :: max'と同じです – 4castle

答えて

1

の1-もSupplier<M>を受け入れtoMapコレクタ方式使用:あなたは置き換えることができ

Map<Integer, Integer> tMap = intervals.stream().collect(Collectors.toMap(i -> i.start, i -> i.end, (i, j) -> i > j ? i : j),() -> new TreeMap<Integer, Integer>()); 

2-:

Set<Map.Entry<Integer, Integer>> set = map.entrySet(); 
for (Map.Entry<Integer, Integer> entry : set) 
{ ... 

で:

map.entrySet().stream().forEach(entry -> { ... 

しかし、私はそれがそうだと思いますそれだけの価値はありません。

+2

' map.forEach((key、value) - > {...});はエントリセットストリームよりも優れたオプションです。 – 4castle

+2

'() - >新しいTreeMap ()'は '() - >新しいTreeMap <>()'または 'TreeMap :: new'で置き換えることができます。それ以外にも、ループの外側で宣言されたローカル変数を変更するので、ループを 'forEach'で置き換えることはできません。 – Holger

+0

ラムダを使ってマップをツリーマップにする方法は本当にスマートです!しかし、最終的なものではない 'tmpLeft'と' tmpRight'を修正してから2番目のものについては分かりません。しかし、あなたの応答に感謝します! –

1

あなたは

Map<Integer, Integer> map = intervals.stream() 
    .collect(Collectors.toMap(i -> i.start, i -> i.end, Math::max, TreeMap::new)); 

にごTreeMap作成を簡素化することができますが、実際には、TreeMapはその出発点でソートされた間隔データを取得するための唯一のその場しのぎです。ソートされたストレージが本当に必要な場合はTreeMapで十分ですが、1回限りのソートでは最も効率的なソリューションではありません。

あなたは使用することができます:

intervals = intervals.stream() 
    .sorted(Comparator.comparingInt(i -> i.start)) 
    .collect(Collectors.toList()); 
int left = Integer.MAX_VALUE, right = Integer.MAX_VALUE, tmpLeft = -1, tmpRight = -1; 
// proceed with your loop as before, 
// using i.start and i.end instead of entry.getKey() and entry.getValue() 
for(Interval i: intervals) 
{ 
    … 

しかし、ここではコレクションAPIを使用した方が効率的かもしれません。いずれの場合も

intervals = new ArrayList<>(intervals); 
intervals.sort(Comparator.comparingInt(i -> i.start)); 
int left = Integer.MAX_VALUE, right = Integer.MAX_VALUE, tmpLeft = -1, tmpRight = -1; 
// proceed with your loop as before, 
// using i.start and i.end instead of entry.getKey() and entry.getValue() 
for(Interval i: intervals) 
{ 
    … 

、新しいリストが作成され、ドンあなたと仮定しますパラメータリストを変更し、そのリストの実装の詳細とは独立したものにしたい

ループのロジックはストリーム操作として表現できますが、ループとしては簡単ではありません。ループ内で実行しているのとほぼ同じ操作を行うカスタムコレクタと、並列操作をサポートするために2つのリストで同様のことを行うマージ関数が必要です。

+0

答えにHolgerをありがとう。最近私が "Java Functional Programming"という本を読んでいて、試したかったので、ストリームとラムダについて尋ねました。しかし、これは本当に良い解決策です!どうもありがとうございました! –

関連する問題