2016-04-22 5 views
0

Я пишу программу, в которой хранятся данные о футбольных командах на вложенной карте деревьев. Это выглядит следующим образом:Java print TreeMap упорядоченными значениями

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

Где, как [название команды] и [противников] являются строками и [команда побеждает] является внутр. Моя текущая цель - распечатать данные, побеждает команда в порядке убывания. Он должен выглядеть следующим образом:

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

На высоком уровне вы должны использовать Список для хранения противников, а затем вызвать Collections.sort() для сортировки списка перед его печатью. – dsh

ответ

1

TreeMap's (as the documentation states) сортируется по ключевым словам, которые вы используете. Итак, если вы хотите распечатать данные по количеству побед, вам нужно сделать число побед в качестве основного ключа.

Поскольку вы хотите, чтобы ваш вторичный сорт основывался на имени команды, вы хотели бы, чтобы это был ваш вторичный ключ.

Поэтому TreeMap<[wins], TreeMap<[team name], [opponents]>> будет правильным подходом.

Кроме того, поскольку противники подразумевают более одного противник вы можете сделать его немного более сложным, и изменить его на следующее, если это необходимо:

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

Надеется, что это указует вам в правильном направление. Помните, что естественный порядок в вашем случае будет DESCENDING для внешнего TreeMap i.e для [wins], так что убедитесь, что функция Comparison's 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, то вы перебрать все команды оригинального KEYMAP и добавить их в sortedKeys, используя победы, как ключ и ключ в вашем TreeMap в качестве значения.
Затем вы можете просто перебирать отсортированныеKeys, чтобы получить ключи в отсортированном порядке, и, таким образом, вы также можете получить результаты в отсортированном порядке.

EDIT: Поскольку ключи не могут быть уникальными, другим решением было бы создать 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 <[выигрывает], TreeMap <[team], [oponents] >>. Проблема, как @Sanchit и я обсуждал выше, заключается в том, что у вас не может быть многоуровневых команд с одинаковыми выигрышами, потому что ключи карты должны быть уникальными. – Alex

+0

@Alex Смотрите мое обновление. Не слепо заменяйте. Сначала проверьте. – Sanchit

+0

Спасибо, человек, ваш ответ и совместная работа Санхита проливают свет на мою проблему. Это похоже на жизнеспособное решение. Я это проверю. Также спасибо за пару. Имеет смысл не использовать карту с одной записью. Я посмотрю эти пары вверх. – Alex

Смежные вопросы