2016-04-22 38 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