2017-08-31 1 views
-1

J'ai créé une carte de hachage qui regroupe des clés uniques combinant trois paramètres, à savoir client, sc et admin. Je veux créer une liste unique de clés avec une liste de serveurs attachés. Je l'ai mis en œuvre les éléments suivants:Comment puis-je itérer sur les résultats d'une carte de hachage dont la valeur est une liste?

public static void main(String[] args) { 

     String items = "customer1^sc1^admin1|server1~" + 
       "customer1^sc1^admin1|server2~" + 
       "customer1^sc1^admin1|server3~" + 
       "customer2^sc1^admin1|server1~" + 
       "customer3^sc1^admin1|server3~" + 
       "customer3^sc1^admin1|server2~"; 

     // Set up raw data 
     List<String> splitItems = Arrays.asList(items.split("\\s*~\\s*")); 

     // Display raw data 
     System.out.println("Raw List: " + items); 

     // Create a hash map containing customer name as key and list of logs as value 
     HashMap<String, List<String>> customerHashMap = new HashMap<>(); 

     // Loop through raw data 
     for (String item : splitItems) { 

      // Create new lists. One for customers and one for logs 
      // List<String> customerList = new ArrayList<>(); 
      List<String> logList; 

      String list[] = item.split("\\|"); 

      String customer = list[0]; 
      String log = list[1]; 

      logList = customerHashMap.get(customer); 
      if (logList == null){ 
       logList = new ArrayList<>(); 
       customerHashMap.put(customer, logList); 
      } 

      logList.add(log); 
      // System.out.println(logList); 
     } 

     // Print out of the final hash map. Customer "a" should only have "a" logs, customer "b" with "b", etc. 
     System.out.println(""); 
     List<String> hashMapList = new ArrayList<String>(); 
     Iterator it = customerHashMap.entrySet().iterator(); 
     while (it.hasNext()) { 
      Map.Entry pair = (Map.Entry) it.next(); 
      String output = pair.getKey() + "|" + pair.getValue().toString(); 
      hashMapList.add(output); 
      it.remove(); 
     } 

     String hashMapResultString = hashMapList.toString(); 
     String hashMapResultFormatted = hashMapResultString.replaceAll("[\\[\\]]", ""); 
     System.out.println(hashMapResultFormatted); 

    } 

Liste Raw:customer1^sc1^admin1|server1~customer1^sc1^admin1|server2~customer1^sc1^admin1|server3~customer2^sc1^admin1|server1~customer3^sc1^admin1|server3~customer3^sc1^admin1|server2~

Carte Hash Chaîne:

customer2^sc1^admin1|server1, customer3^sc1^admin1|server3, server2, customer1^sc1^admin1|server1, server2, server3 

Je veux maintenant utiliser la carte de hachage pour créer une chaîne qui sera analysé plus loin (ne demandez pas lol). Donc, je définis les clés et les valeurs de la carte de hachage à une chaîne qui les sépare avec un délimiteur unique |. Le problème est que parce que la clé est un List<String>, lors de l'impression, je ne peux pas déterminer le début de chaque nouveau key si sa valeur est une liste avec plus d'un élément, à savoir customer3^sc1^admin1|server3, server2, est immédiatement suivi par customer1^sc1^admin1|server1, server2, server3. J'ai besoin d'un délimiteur ici qui les sépare.

Ma sortie idéale ressemblerait à ceci:

customer2^sc1^admin1|server1~customer3^sc1^admin1|server3, server2~customer1^sc1^admin1|server1, server2, server3~... 

Comment puis-je y parvenir?

Mise à jour:

Ceci est la réponse que je finalement trouvé utile pour mon problème particulier:

StringBuilder s = new StringBuilder(); 
     for (Map.Entry<String, List<String>> entry : customerHashMap.entrySet()) { 
      s.append(entry.getKey() + "|"); 
      List<String> list = entry.getValue(); 
      for (String item : list) { 
       if (item != list.get(list.size() - 1)) { 
        s.append(item + "^"); 
       } else { 
        s.append(item); 
       } 
      } 
      s.append("~"); 
     } 
     System.out.println(s.toString()); 
+0

Vous semblez mal comprendre, 'HashMap >' ici c'est la valeur d'une liste, pas la clé (comme dit dans le titre) – azro

+0

Désolé. Mauvaise faute de frappe. Vous verrez que dans la question elle-même, je suis plus cohérent. – santafebound

Répondre

1

Vous pouvez parcourir l'ensemble d'entrée d'une carte:

StringBuilder s = new StringBuilder(); 
for(Map.Entry<String,List<String>> entry : map.entrySet()) { 
    s.append(entry.getKey() + "\n"); 
    List<String> list = entry.getValue(); 
    for(String item : list) { 
     s.append(" " + item + "\n"); 
    } 
} 
return s.toString(); 

Pour la Par souci d'un exemple plus clair, j'ai sorti un format différent de celui que vous avez demandé, mais cela illustre comment travailler avec une carte de la liste v alues. Lors de l'adaptation à vos besoins, jetez un oeil à java.util.StringJoiner et le Collectors.joining(); cela pourrait bien être utile.


Streams peut être pratique ici:

String encoded = map.entrySet().stream() 
    .map(entry -> entry.getValue().stream() 
       .collect(Collectors.joining("^")) 
      + "|" + entry.getKey()) 
    .collect(Collectors.joining("~")); 

Ce qui se passe ici est:

  • Nous obtenons un flux de Entry<String,List<String> sur la carte
  • Le lambda entry -> ... convertit chaque entrée dans une chaîne de la forme val1^v2^v3^...^valN|key, à savoir que nous sommes en train de mapper un Stream<Entry<>> dans un Stream<String>.
  • le collect() final joint le flux de chaînes dans une chaîne unique en utilisant ~ en tant que délimiteur.
+0

Je pense que la solution ici serait de supprimer le ** caractère suivant ** après l'apparition d'un autre caractère, c'est-à-diresupprime le ** suivant ** '', '' après chaque '' ~ ''. – santafebound

+0

@santafebound vous parlez d'un problème général concernant les listes de virgules. Il est préférable de ne pas ajouter de séparateurs indésirables, que de les ajouter puis de les supprimer. Jetez un oeil à la source de StringJoiner - http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/StringJoiner.java - ils le font un pur façon. – slim

+0

@santafebound mais si vous voulez juste l'effet, utilisez StringJoiner au lieu d'écrire le vôtre - c'est ce à quoi cela sert. – slim