使用Lambdas在Java中部分展平嵌套的集合

时间:2019-06-06 19:05:49

标签: java lambda collections

我有这样的嵌套集合

Map<Integer, Map<Integer, List<Integer>>> nodes = new TreeMap<>()

我需要将内部映射转换为List<List<Integer>>。内部列表的顺序必须保留。本质上,对于外部映射中的每个条目,迭代内部映射,将List原样添加到List of List。

我可以用老式的方式来做。

    List<List<Integer>> result = new ArrayList<>();
    for(Map.Entry<Integer, TreeMap<Integer, List<Integer>>> entry : nodes.entrySet()) {
        Map<Integer, List<Integer>> outer = entry.getValue();
        ArrayList<Integer> tmp = new ArrayList<>();
        for (Map.Entry<Integer, List<Integer>> inner : outer.entrySet()) {
            tmp.addAll(inner.getValue());
        }
        result.add(tmp);
    }

如何使用lambdas?这不起作用

nodes.entrySet().stream().flatMap(e -> e.getValue().entrySet().stream()).map(e2 -> result.add(e2.getValue()))

2 个答案:

答案 0 :(得分:2)

  

如何使用lambdas?这不起作用

在这里您永远不会调用终止操作,因此永远不会消耗该流。 :

<DOCTYPE! html>
<html lang="en-US" dir="ltr">
    <head>
        <meta name="viewport" content="width=device-width">
        <meta charset="UTF-utf-8">
        <title>100 Thieves | Home</title>
        <link rel="stylesheet" href="style.css">
        <link href="https://fonts.googleapis.com/css?family=Barlow&display=swap" rel="stylesheet">
        <script src="https://kit.fontawesome.com/ab11039b93.js"></script>
    </head>
    <body>
        <header>
            <div class="main-logo">
                <a href="index.html"><img src="Img/100Thieves.png" alt="100 Thieves Logo"></a>
            </div>

            <div class="main-nav">
                <nav>
                    <ul>
                      <li><a href="#">About</a></li>
                      <li><a href="#">Store</a></li>
                      <li><a href="#">Teams</a></li>
                      <li><a href="#">Partners</a></li>
                      <li><a href="#">Careers</a></li>
                    </ul>
                </nav>
            </div>
        </header>

        <div class="intro-content">
            <h1>Take What's Not Given</h1>
            <p>The words of Matt "Nadeshot" Haag and the official 100 Thieves motto</p>
        </div>

        <div class="main-content">

          <div class="about">
            <h2>About 100 Thieves</h2>
            <p>100 Thieves is a new gaming lifestyle company and eSports organization built at the intersection of competitive gaming, entertainment, and apparel. 100 Thieves was founded in 2017 by Matt "Nadeshot" Haag, the former Optic Gaming Call of Duty captain, X Games gold medalist, and 2014 eSports athlete of the year.
            After retiring from competitive play, Matt went on to build some of the most popular gaming channels on twitch and youtube, and then founded 100 Thieves as a creative outlet for his passions in competitive gaming, storytelling, and streetwear. The company currently competes in professional League of Legends, Call of Duty, Fortnite and Apex Legends.
            </p>
          </div>

          <div class="cashapp">
            <h2>About Cash App</h2>
            <p>Cash App is the money app. It's the easiest way to pay people back—friends, family, coworkers—anyone, really. Sending and receiving money is totally free and fast, and most payments can be deposited directly to your bank account in just a few seconds. With cash app, you can also buy and sell bitcoin instantly, get a paycheck deposited right to the app, or create a unique $cashtag that you can share with anyone to get paid fast. You can even use the free cash card to spend the money you keep in the app anywhere you like. Customize your card with a laser-etching and add a boost from the app to instantly save at some of your favorite places whenever you swipe.
            <a href="http://www.cash.app/download">Download</a> cash app for free.
            </p>
          </div>

        </div>

        <div class="secondary-content t-border group">

          <div class="article1">
            <img src="Img/win.png" alt="100 Thieves wins at CWL London">
            <h2>Big Win at CWL London</h2>
            <p>100 Thieves won their first ever Call of Duty eSports title on May 5, 2019. After knocking out top teams like Envy, Team Heretics, and Team Reciprocity, and sweeping OpTic Gaming aside with ease, 100 Thieves was matched against eUnited. It was a close fought affair all through the match, and with both teams mere seconds away from claiming victory, 100 Thieves managed to hold on to the point and won the final map 250-238.
            <p><a href="https://www.gamesradar.com/cwl-london-2019-recap-winner/">Read more...</a></p>
          </div>

          <div class="article2">
            <img src="Img/franchise.png" alt="100 Thieves gunning for the Los Angeles franchise">
            <h2>Gunning the Los Angeles Franchise</h2>
            <p>One of the most sought after spots in the competition is the Los Angeles franchise, and according to reports 100 Thieves are hoping to raise more money in the hopes of locking down the California position. If successful, it’s believed that 100 Thieves would be the sole team based in Los Angeles in the Call of Duty franchise league, an ideal situation as the team’s headquarters and LCS teams are both based in the city.</p>
            <p><a href="https://www.dexerto.com/call-of-duty/100-thieves-reportedly-raising-25-million-for-call-of-duty-franchise-spot-675708">Read more...</a></p>
          </div>
        </div>

        <div class="socialmedia">
          <h3>Follow 100 Thieves</h3>
          <a href="https://twitter.com/100Thieves"><i class="fab fa-twitter"></i></a>
          <a href="http://instagram.com/100thieves"><i class="fab fa-instagram"></i></a>
          <a href="https://www.youtube.com/100thieves"><i class="fab fa-youtube"></i></a>
          <a href="https://www.twitch.tv/team/100thieves"><i class="fab fa-twitch"></i></a>
        </div>

      <div class="main-footer">
        <footer>
          &copy; 100 Thieves, LLC 2019
        </footer>
      </div>
    </body>
</html>

添加任何终端操作,例如nodes.entrySet().stream().flatMap(e -> e.getValue().entrySet().stream()).map(e2 -> result.add(e2.getValue())) ,您会看到流已运行。
不要忘记Streams是惰性的,因此只有在调用终端操作时才有效地执行计算。

因此,您可能认为自己的方法不是使用Stream进行处理的正确方法。
您无需将count()用作要在流中填充的变量。流被设计为在产生结果时进行收集,并且收集到List的过程最终是您的初始代码中缺少的终端操作。

此外,由于您从不使用键,因此您应该仅流式传输每个Map级别的值而不是条目。
这里的代码具有每一步的实际返回类型:

List

答案 1 :(得分:1)

这应该可以解决问题:

Map<Integer, Map<Integer, List<Integer>>> nodes = new TreeMap<>();
List<List<Integer>> list = nodes.values()
    .stream()
    .flatMap( map -> map.values().stream() )
    .collect( Collectors.toList() );

说明: 首先,您可以使用以下方法从地图中获取地图流:

nodes.values().stream()

然后使用以下方法将这些地图展平:

.flatMap( map -> map.values().stream() )

最后用它们收集它们:

.collect( Collectors.toList() )