1
votes

Comment convertir une liste en carte en utilisant la liste comme clé en Java

Je lis un tableau Excel contenant quatre colonnes et crée une liste. Maintenant, j'aimerais utiliser les trois premières colonnes comme clé et utiliser la dernière colonne comme valeur. J'ai vu des questions similaires posées, mais dans toutes ces questions, String ou Integer est utilisé comme clé.

Map<myTuple, Integer> myMap= myList.stream().collectC(ollectors.toMap(myList:: , myList::));

Je ne sais pas comment procéder après ce point. Je pense que je devrais utiliser quelque chose comme;

public class initial {
private int from;
private int to;
private int via;
private int cost;
//constructor
//set and get methods
//hashCode and equals methods
}

public class myTuple {
private int from;
private int to;
private int via;
}

 //main function
 //get the Excel Table as a list
ArrayList<initial> myList = new ArrayList<initial>();

for(int i= mySheet.getFirstRowNum()+1 ; i<= mySheet.getLastRowNum(); i++) {
   initial e = new initial();
   Row ro = mySheet.getRow(i);
   for(int j = ro.getFirstCellNum(); j <= ro.getLastCellNum();  j++) {
    Cell ce = ro.getCell(j);
    switch(j) {
    case 0:
      e.setFrom((int) ce.getNumericCellValue());
          break;
              .....

    case 3:
      e.setCost((int) ce.getNumericCellValue());
      break;    
    }
}
myList.add(e);
}

//Create map
Map<myTuple, Integer> myMap = new HashMap<>();

Si quelqu'un pouvait m'aider, j'apprécierais vraiment.

De plus, si vous pensez qu'il existe un moyen plus efficace de faire cela (par exemple, la façon dont je lis mes données et les analyse en une liste, la façon dont je convertis la liste en carte), veuillez laisser je sais. Même si ce n'est pas dans le contenu de cette question, s'il existe une meilleure façon de lire un tableau multidimensionnel et d'analyser une liste comme je le fais, j'aimerais bien l'entendre aussi. À l'avenir, j'aurai des tables plus grandes avec plus de colonnes. Par conséquent, je ne suis pas tout à fait sûr de savoir si parcourir chaque colonne avec une instruction switch est la voie à suivre.


3 commentaires

Créez une classe Tuple qui contiendra ces trois valeurs et remplacera les méthodes equals et hashcode pour cela. Ensuite, vous pourrez l'utiliser comme clé dans les collections de hachage.


Avez-vous réellement besoin de créer la liste, c'est-à-dire en avez-vous besoin plus tard? Il me semble qu'il est plus facile de créer simplement la carte dans la boucle.


Est-ce une "importation" unique? Je demande souvent à Excel de générer du code Java et de le coller dans mes scripts. Par exemple: = "myMap.put (new MyTuple (" & A3 & "," & B3 & "," & C3 & ")," & D3 & ")" (facile pour les entiers; un peu plus faff en citant les champs de chaîne).


3 Réponses :


2
votes

Vous pouvez simplement créer la carte en boucle.

Tuple key = new Tuple(row.getNum(0), row.getNum(1), row.getNum(2));
List<Integer> value = new ArrayList<>();
for (int cell = 3; cell < row.getCount(); cell++) {
    value.add(row.getNum(cell));
}
Map.put(key,value);


2 commentaires

Vous avez tout à fait raison! Il était 3 heures du matin et je suppose que mon esprit n'était pas au bon endroit. Merci!


La question comporte exactement 4 colonnes. Vous pouvez supprimer la liste et la boucle. La carte doit être Map et non Map> .



-1
votes

Voici un exemple:

class Tuple implements Comparable<Tuple> {
        Object one;
        Object two;
        Object three;
        public Tuple(final Object one, final Object two, final Object three) {
            this.one = one;
            this.two = two;
            this.three = three;
        }
        @Override
        public int compareTo(final Tuple that) {
            // TODO: Do your comparison here for the fields one, two and three
            return 0;
        }
    }
    Map<Tuple, Object> mapKeyedByCompositeTuple = new HashMap<>();
    // TODO: Inside your loop
    for (int i = 10; i > 0; i--) {
        Tuple key = new Tuple("cell-one-value-" + i, "cell-two-value-" + i, "cell-three-value-" + i);
        mapKeyedByCompositeTuple.put(key, "cell-four-value-" + i);
    }
    System.out.println(mapKeyedByCompositeTuple);

J'espère que cela vous aidera, Acclamations, Michael


1 commentaires

Il n'y a aucune raison d'utiliser Object ici. Tous les champs sont des nombres entiers.



1
votes

Le collecteur toMap a besoin de 2 fonctions (1 pour créer une clé et 1 pour créer une valeur). Vous pouvez utiliser des lambdas (pour extraire les champs pertinents de votre type de source):

Map<MyTuple, Integer> myMap = myList
    .stream()
    .collect(Collectors.toMap(
        i -> new myTuple(i.from, i.to, i.via),
        i -> i.cost
));

Votre type de destination "MyTuple" a besoin d'un constructeur, égal et hashcode.


2 commentaires

Merci! C'est exactement ce que je recherchais. Pour le moment, la création de la carte dans la boucle for a beaucoup plus de sens, comme l'a suggéré @daniu.


Convenu. Si vous êtes déjà obligé de boucler les données source, accédez directement à une carte. Peut-être que cela vous aidera dans un problème futur.