2016-04-22 55 views
0

我正在编写一个程序,用于存储有关足球队在嵌套树状图中的数据。它看起来像这样:Java打印按订单值排列的TreeMap

TreeMap<[team name], TreeMap<[team wins], [opponents]>> 

其中[团队名称]和[对手]是字符串,[团队胜利]是int。 我目前的目标是打印数据,按降序排列。它看起来像:

Liverpool: //map key 
wins: <wins> //nested map key 
opponents: <opponents> 

我的想法就是命令嵌套的entrySet地图(),然后重复它,而打印的数据,但我读书,我需要我不能这样做,因为从TreeSet中和map.entry()只返回Set.I需要我的地图为TreeMap,因为当两个团队有相同的胜利时,我需要按字母顺序打印。如果我不清楚,打印TreeMap的好方法是什么,按照嵌套的TreeMap键进行排序?

+1

你真的有问题吗? –

+0

为了获得体面的帮助,请创建并发布一个体面的[最小,完整和可验证示例](https://stackoverflow.com/help/mcve)。请阅读此重要链接以了解详细信息。 – dsh

+0

在高层次上,您将使用List来存储对手,然后在打印之前调用Collections.sort()对列表进行排序。 – dsh

回答

1

TreeMap的(as the documentation states)自然按您使用的键排序。所以,如果你想通过胜利数量打印数据,那么你需要将胜利数量作为主键。

既然你希望你的二级排序是基于团队名称,那么你会希望这是你的次要关键。因此TreeMap<[wins], TreeMap<[team name], [opponents]>>将是正确的方法。

此外,由于对手将意味着超过一个对手,你可能要使它稍微复杂一点,并将其更改为以下如果需要的话:

TreeMap<[wins], TreeMap<[team name], ArrayList<[opponent]>>>

希望这点你在正确的方向。请记住,您的案例中的自然顺序将是外部TreeMap的降级顺序,即对于[wins],请确保您的Comparable的compareTo函数执行正确的工作。

import java.util.ArrayList; 
import java.util.Comparator; 
import java.util.Random; 
import java.util.TreeMap; 

public class SO36799415 { 

    public static Random random = new Random(); 

    public static void main(String[] args) { 
     TreeMap<Integer, TreeMap<String, ArrayList<String>>> map = new TreeMap(new Comparator<Integer>() { 
      @Override 
      public int compare(Integer o1, Integer o2) { 
       return -Integer.compare(o1, o2); 
      } 
     }); 
     int teams = random.nextInt(20) + 1; 
     for (int i = 0; i < teams; i++) { 
      addToMap(map); 
     } 
     for (Integer wins : map.keySet()) { 
      TreeMap<String, ArrayList<String>> tmp = map.get(wins); 
      for (String team : tmp.keySet()) { 
       System.out.println(team); 
       System.out.println("Wins: " + wins); 
       System.out.println(tmp.get(team)); 
       System.out.println(); 
      } 
     } 
    } 

    private static void addToMap(TreeMap<Integer, TreeMap<String, ArrayList<String>>> map) { 
     String name = randomName(); 
     int wins = random.nextInt(10); 
     int opponents = random.nextInt(10) + 1; 
     Team team = new Team(name); 
     team.setWins(wins); 
     for (int i = 0; i < opponents; i++) { 
      team.addOpponent(randomName()); 
     } 
     if (map.containsKey(wins)) { 
      map.get(wins).put(name, team.opponents); 
     } else { 
      TreeMap<String, ArrayList<String>> tmp = new TreeMap<>(); 
      tmp.put(name, team.opponents); 
      map.put(wins, tmp); 
     } 
    } 

    private static String randomName() { 
     StringBuffer sb = new StringBuffer(); 
     int len = random.nextInt(10) + 1; 
     for (int i = 0; i < len; i++) { 
      sb.append((char) ('a' + random.nextInt(26))); 
     } 
     return sb.toString(); 
    } 

    private static class Team { 
     String name; 
     ArrayList<String> opponents; 
     int wins; 

     public Team(String name) { 
      this.name = name; 
      this.opponents = new ArrayList<>(); 
      this.wins = 0; 
     } 

     public boolean addOpponent(String opponent) { 
      return this.opponents.add(opponent); 
     } 

     public void setWins(int wins) { 
      this.wins = wins; 
     } 
    } 
} 
+0

感谢您的回答。我也这么认为,不幸的是,当我拥有一支以平等胜利作为输入的球队时,这个解决方案就失败了。 – Alex

+0

它没有。你在说什么?你甚至试过这个吗?请分享您的代码。 – Sanchit

+0

基本的java地图,包括TreeMap,必须有唯一的键。如果使用相同的密钥作为新条目 - 它只是覆盖它。这是我的第一次尝试,而我最终只有两支球队:第一次以1胜,第二次以0胜。在好的方面,它被命令:D – Alex

1

我想创建一个名为TreeMap<Integer, String>又如sortedKeys,那么你遍历你原来的键盘映射的所有球队,并将它们添加到使用WINS为重点,并在您TreeMap中作为值的关键又如sortedKeys。
然后,您可以迭代sortedKeys以按排序顺序获取键,从而以排序顺序获得结果。

编辑:由于密钥不可能是唯一的,所以另一个解决方案是用你自己的比较器创建一个TreeSet对,当密钥相等时比较值。然后你会得到这样的事情:

TreeSet<Pair<String,Pair<Integer,String>>> sortedSet = new TreeSet(new Comparator<Pair<String,Pair<Integer,String>>>() { 
    @Override 
    public int compare(Pair<String,Pair<Integer,String>> a, Pair<String,Pair<Integer,String>> b) { 
     int res = b.getValue().getKey() - a.getValue().getKey(); 
     if (res == 0) { 
      return a.getKey().compareTo(b.getKey()); 
     } else { 
      return res; 
     } 
    } 
}); 
teams.forEach(new BiConsumer<String,Pair<Integer,String>>() { 
    @Override 
    public void accept(String k, Pair<Integer,String> v) { 
     sortedSet.add(new Pair(k, v)); 
    } 
}); 

我一点点的方式改变了你的初始数据结构,因为你指出球队只对一个胜值,这意味着嵌套TreeMap中总是只有一个入口,因此应该只是一对。

+0

嗯,我也可以这样构建我的嵌套地图:TreeMap <[wins],TreeMap <[team],[oponents] >>。作为@Sanchit和我上面讨论的问题是,你不能有多个具有相同胜利的团队,因为Map键需要是唯一的。 – Alex

+0

@Alex查看我的更新。不要盲目更换。先检查。 – Sanchit

+0

谢谢你,你的回答和Sanchit的结合为我的问题提供了一些启示。这看起来像一个可行的解决方案。我会看看。也感谢这对夫妇。只有一个条目不使用地图是有意义的。我会看那些对。 – Alex