Comparer 2 ArrayList pour incrémenter une valeur

Résolu/Fermé
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018 - Modifié le 24 mai 2018 à 09:55
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018 - 5 juin 2018 à 09:25
Bonjour à tous,

Tout d'abord je précise que c'est du Java EE si besoin.
Pour faire simple, j'ai une ArrayList "outilBrut" aves des doublons,
je ne dois pas toucher à ce premier conteneur donc je créé une ArrayList "outil" que je remplis avec la première sans les doublons.

 public static void antiDoublon()
    {
        for (int i = 1; i < outilBrut.size(); i++)
        {
            if (!outilBrut.get(i).getDesignation().equals(outilBrut.get(i-1).getDesignation()))
            {
                outil.add(outilBrut.get(i));
            }
        }
    }


Mes ArrayList sont remplis d'objets "Outil" avec un certain nombre d'attributs mais surtout deux,
"designation" qui est un String (le nom de l'outil) et "quantite" qui est donc un int.

Je voudrais comparer ces ArrayList afin de faire en sorte que le nombre de "designation" en plus dans ma première AL incrémente la "quantité" de l'outil concerné dans la seconde AL, voici ce que j'ai tenté :

public static void setQte()
    {
        for (int i = 0; i < outilBrut.size(); i++)
        {
            String brut = outilBrut.get(i).getDesignation();

            for (int j = 0; j < outil.size(); j++)
            {
                if (brut.equals(outil.get(j).getDesignation()))
                    outil.get(i).setQuantite(outil.get(i).getQuantite()+1);
            }

        }
    }

Ce n'est pas optimisé du tout je le sais, d'ailleurs ça ne marche pas (IndexOutOfBoundsException : Index 248 out-of-bounds for length 248) mais je ne vois pas comment faire, j'utilise ma tête plus que certains outils que je connais peu voire pas.

Merci d'avance.

Edit : "outil.get(i).setQuantite(outil.get(i).getQuantite()+1);" j'ai remplacé des i par des j, je remplissais avec le mauvais indice, maintenant j'ai des quantités de 3 pour chaque objet, ce qui est faux..

A voir également:

5 réponses

KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
24 mai 2018 à 11:55
Bonjour,

Le choix des List dans ce traitement paraît mal adapté.

Les Set permettent de stocker les valeurs sans doublons.
https://docs.oracle.com/javase/10/docs/api/java/util/Set.html

Quant aux Map elles permettent de faire des recherches par clés (la désignation dans ton cas).
https://docs.oracle.com/javase/10/docs/api/java/util/Map.html

Et pour bien comprendre, sur un exemple, ce que tu cherches à calculer c'est ça ?
[(ciseaux,2),(marteau,3),(tournevis,1),(marteau,2)] → [(ciseaux,2),(marteau,5),(tournevis,1)]

Remarque : tu as un problème de conception objet. Mettre le nombre d’occurrences d'un objet dans l'objet lui même c'est incorrect. Modifier le nombre d'objets ne devrait pas avoir d'effets sur les objets eux même.
1
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
24 mai 2018 à 12:46
Merci de ta réponse j'ai pris le temps de lire et relire ce que tu as écris.

- Je vais m'attaquer a l'apprentissage des HashSet et HashMap cette après-midi alors :)

- Ton exemple est parfait c'est ce que je cherche à faire, je récupère le tout d'un fichier Excel (j'ai posté sous le nom de CocoLm y a peu de temps) il n'y a pas de quantité de base, et vu que l'application finale sera un inventaire, dans le constructeur des "Outil" j'initialise la valeur à 1 directement, il ne me reste qu'a incrémenter la valeur en fonction des doublons.

- Je comprends à peu près ta remarque mais je ne saurais y remédier, je suis en cours d'apprentissage et c'est assez compliqué pour moi, mais je suis totalement motivé
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015 > TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
24 mai 2018 à 13:36
Si tu as une notion d'inventaire c'est ça qu'il faut utiliser pour lier des outils à leurs quantité.

Par exemple avec une Map<String, Integer> qui lie les désignations d'outils à leurs quantités dans l'inventaire précis.

Ton code reviendrait alors à agglomérer une liste d'inventaires, mais sans jamais manipuler les outils au final.
0
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
Modifié le 24 mai 2018 à 15:53
Nickel, le Set marche mais je ne dois pas bien m'y prendre, l'ArrayList est facile à manipuler.. :

public class CommandeOutils implements Commande
{
    private final  String           next;
    private static FileOutputStream fos;
    private static Row              row;
    private static Cell             cell;

    public static ArrayList<Outil> outilBrut = new ArrayList<Outil>();
    public static ArrayList<Outil> outil;

    public static Set<Outil> outilTmp = new HashSet<>();

    public CommandeOutils(String next) {
        this.next = next;
    }

    public String execute(HttpServletRequest req) throws Exception
    {
        readExcel();
        req.setCharacterEncoding("UTF-8");
        req.getServletContext().getRequestDispatcher("/WEB-INF/outils.jsp");
        return next;
    }

    //Compter quantité, calculer différence entre le nombre de "désignation" de différence entre les 2 al

    public void readExcel() throws IOException, InvalidFormatException
    {
        FileInputStream fis = new FileInputStream("C:\\Users\\lomoc\\Cours\\S4\\JSP\\webapps\\Actemium\\WEB-INF\\outillage.xls");
        Workbook wb = WorkbookFactory.create(fis);
        Sheet sh = wb.getSheet("listing");
        int noOfRows = sh.getLastRowNum();
        for (int i = 1; i < noOfRows; i++)
        {
            if (sh.getRow(i) == null)
            {
                out.print("N/A");
                break;
            }
            outilBrut.add(new Outil(
                    sh.getRow(i).getCell(0).toString(), sh.getRow(i).getCell(1).toString(),
                    sh.getRow(i).getCell(2).toString(), sh.getRow(i).getCell(3).toString(),
                    sh.getRow(i).getCell(4).toString(), sh.getRow(i).getCell(5).toString(),
                    sh.getRow(i).getCell(6).toString(), sh.getRow(i).getCell(0).toString(),
                    sh.getRow(i).getCell(8).toString(), sh.getRow(i).getCell(9).toString(),
                    sh.getRow(i).getCell(10).toString(), sh.getRow(i).getCell(11).toString(),
                    sh.getRow(i).getCell(12).toString(), sh.getRow(i).getCell(13).toString(),
                    sh.getRow(i).getCell(14).toString(), sh.getRow(i).getCell(15).toString(),
                    sh.getRow(i).getCell(16).toString(), sh.getRow(i).getCell(17).toString()));


        }
        outilTmp.addAll(outilBrut);
        outil = new ArrayList<Outil>(outilTmp);
    }

}


Même si c'est peut être mal fait ça marche, mais ce n'est plus trié, le Collections.sort() ne marche pas vu que j'ai créé mes propres objets, aurais tu une piste pour moi ? Je crois que je dois définir un comparableTo mais je ne sais pas où ni comment le faire, je vois de tout sur le net.

Edit : J'ai implements la classe Outil avec Comparable et donc définit un comparableTo, tout va bien, mais vu que ma conception est ratée.. les doublons sont revenus, et à chaque refresh de la page, les objets se multiplient...
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
Modifié le 24 mai 2018 à 23:19
"ce n'est plus trié"

Set est une interface qui garantie l'absence de doublon, mais ne dit rien sur l'ordre. Il y a plusieurs implémentations :
  • le HashSet (non trié), qui pour fonctionner correctement nécessite que tu es recodé hashCode et equals.
  • le TreeSet (trié) qui implémente une interface plus précise, le SortedSet, qui nécessite que les objet soient Comparable, ou que l'on passe un Comparator dans le constructeur du TreeSet.

Donc le Comparable c'est bien, mais ça ne sert à rien avec un HashSet.
Essayes plutôt
SortedSet<Outil> outilTmp = new TreeSet<>();


Pour t'aider, il serait sûrement utile que tu copies-colles le code de ta classe Outil.
En particulier les méthodes hashCode, equals et/ou compareTo.

Remarque : dans ta classe commandeOutil je pense que tous les static sont faux, ça ressemble plutôt à des variables locales. De plus attention avec les flux, tu ne les as pas fermé, je te conseilles de faire des try-with-resources.
0
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
28 mai 2018 à 10:51
Je vais regarder tout ça aujourd'hui, merci.
J'entrepose plus bas ma classe Outil.

Le problème ici c'est que j'ai déjà réalisé un premier projet comme celui mais avec une base de données postresql, ici on me demande de simuler une bdd avec un fichier Excel, c'est à dire lire et écrire dans le fichier Excel en passant par ma future application.


Voilà comment j'ai imaginé la chose, les outils sont dans l'ordre du fichier Excel, j'enlève les doublons, du coup j'augmente la quantité pour l'objet visé. Une fois fonctionnel, je rentre la quantité, je valide (rond blanc qui est un checkbox) et le changement est fait et sauvegarde le fichier Excel.


Les variables de ma classe Outil sont toutes des String par facilité d'obtention de données.
package pac.bdd.beans;


import java.util.Comparator;

public class Outil implements Comparable<Outil>
{
    private String  designation;
    private String  numInterne;
    private String  numSerie;
    private String  marque;
    private String  classement;
    private String  dateAchat;
    private String  dateFinDeVie;
    private String  verifInterne;
    private String  verifExterne;
    private String  derniereVerification;
    private String  prochaineVerification;
    private String  observation;
    private String  utilisateur;
    private String  dateSortie;
    private String  utilisateurPrecedent;
    private String  dateRetour;
    private String  conforme;
    private String  nonConforme;

    private int     quantite;

    public Outil(String designation, String numInterne, String numSerie, String marque, String classement,
                 String dateAchat, String dateFinDeVie, String verifInterne, String verifExterne,
                 String derniereVerification, String prochaineVerification, String observation, String utilisateur,
                 String dateSortie, String utilisateurPrecedent, String dateRetour, String conforme, String nonConforme)
    {
        this.designation = designation;
        this.numInterne = numInterne;
        this.numSerie = numSerie;
        this.marque = marque;
        this.classement = classement;
        this.dateAchat = dateAchat;
        this.dateFinDeVie = dateFinDeVie;
        this.verifInterne = verifInterne;
        this.verifExterne = verifExterne;
        this.derniereVerification = derniereVerification;
        this.prochaineVerification = prochaineVerification;
        this.observation = observation;
        this.utilisateur = utilisateur;
        this.dateSortie = dateSortie;
        this.utilisateurPrecedent = utilisateurPrecedent;
        this.dateRetour = dateRetour;
        this.conforme = conforme;
        this.nonConforme = nonConforme;

        this.quantite = 1;
    }

    /**Getters & Setters**/

    @Override
    public int compareTo(Outil o)
    {
        return Comparators.NOM.compare(this, o);
    }


    public static class Comparators
    {
        public static Comparator<Outil> NOM = new Comparator<Outil>()
        {
            @Override
            public int compare(Outil o1, Outil o2) {
                return o1.getDesignation().compareTo(o2.getDesignation());
            }
        };
    }
}
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
28 mai 2018 à 13:06
Et du coup, quel est le problème désormais ?

Remarque : pour ton Comparator ça se simplifie.

@Override
public int compareTo(Outil o) {
    return this.getDesignation().compareTo(o.getDesignation());
}

Et éventuellement :

public static final Comparator<Outil> NOM = Comparator.comparing(Outil::getDesignation);

@Override
public int compareTo(Outil o) {
    return NOM.compare(this, o);
}

Quant au fait que tu ne manipules que des String je pense que c'est une erreur, si tu as des entiers, ou des dates, il faut les convertir, notamment pour faire des calculs dessus, et vérifier que le fichier Excel ne contienne pas d'erreur.

Idée d'amélioration : au lieu de ta longue liste de colonnes, tu pourrais la traiter dans une enum Java.

Exemple :

enum OutilProperty {
    DESIGNATION("designation", String::valueOf), // colonne 0, libellé "designation", de type String
    NUMERO_INTERNE("numInterne", Integer::valueOf), // colonne 1, libellé "numInterne", de type Integer
    ...

    private OutilProperty(String label, Function<String, Object> converter) {
    ...

Tu pourras alors manipuler toutes tes données avec une EnumMap par exemple.

EnumMap<OutilProperty, Object> outilProperties = new EnumMap<>(OutilProperty.class);
OutilProperty[] properties = OutilProperty.values();
for (int j = 0; i<properties.length; i++) {
    String str = sh.getRow(i).getCell(i);
    Object obj = properties[j].converter(str);
    outilsProperties.put(properties[j], obj);
}

Vu comme ça, on dirait que c'est plus compliqué, mais ça évite la redondance à avoir sh.getRow(i).getCell(0).toString(), sh.getRow(i).getCell(1).toString(), ... sh.getRow(i).getCell(17).toString()

Si tu ajoutes/supprimes une colonne dans ton fichier Excel, ou même juste si tu en déplaces une, le changement dans le code est beaucoup plus simple, il suffit de modifier l'enum et tout le reste du code est identique.
0
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
Modifié le 28 mai 2018 à 15:30
Je suis actuellement en DUT Informatique, en Collections j'ai vu ArrayList et HashMap, tes 2 derniers posts sont de nouvelles choses pour moi, je fais une sauvegarde, j'essaie tout ça et je reviens donner le résultat.

Je viens de regarder à quoi ressemble les enum, c'est Ok, je regarde juste après comment les manipuler.
De ce que je comprends, ma classe Outil devient obsolète avec un enum plus modulaire. Le fichier Excel ne changera pas, seul le nombre de ligne changera.

Edit : DESIGNATION("designation", String::valueOf) Je comprends bien, mais je ne vois pas quoi mettre pour une date
0
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
28 mai 2018 à 17:21
Double post désolé, j'ai donc réussi à régler :
- Doublons,
- Ordre Alphabétique
Problème restant :
- Augmenter le nombre de "quantité" en fonction du nombre de doublons à partir des noms d'outils.
Je suis entrain de voir comment gérer l'interface Map, si j'ai bien compris l'idée est de remplir un Map<String, Integer> avec mon TreeSet (avec un iterator si besoin), le principe de clé est un peu flou dans ma tête mais en gros en fonction de la clé, si une même clé est déjà stockée dans la Map, la valeur sera incrémentée.

Merci du temps déjà accordé
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015 > TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
28 mai 2018 à 18:18
"De ce que je comprends, ma classe Outil devient obsolète avec un enum plus modulaire. Le fichier Excel ne changera pas, seul le nombre de ligne changera."
Oui, chaque valeur de l'enum correspondra à une colonne du fichier Excel, là où avant cela correspondait à un attribut private String. Tu avais 17 attributs pour 17 colonnes, là tu aurais 17 valeurs dans l'enum.

"DESIGNATION("designation", String::valueOf) Je comprends bien, mais je ne vois pas quoi mettre pour une date"
Tout dépend ce que tu veux faire, c'est un code que j'ai fait rapidement ce midi, et qu'il faut peut-être retravailler.
Pour transformer un String en Date, il y a plusieurs méthodes, cela dépend surtout de comment sont écrites les dates dans le fichier Excel. Il faudra peut-être aussi envisager d'ajouter la méthode de conversion dans l'autre sens.
Mais c'était une idée d'amélioration, il ne faut pas que ça te bloque plus que ça.

"le principe de clé est un peu flou dans ma tête mais en gros en fonction de la clé, si une même clé est déjà stockée dans la Map, la valeur sera incrémentée."
Tu peux considérer ça comme un dictionnaire. La clé c'est le mot que tu cherches. La valeur c'est la définition de ce mot dans le dictionnaire. Ici ta clé sera très certainement la désignation de ton outil et la valeur la quantité de cet outil.

Exemple de somme de deux maps :

public static Map<String, Integer> somme(Map<String, Integer> map1, Map<String, Integer> map2) {
    Map<String, Integer> result = new TreeMap<>();

    Set<String> keys = new TreeSet<>(map1.keySet());
    keys.addAll(map2.keySet());

    for (String key : keys) {

        Integer val1 = map1.get(key);
        if (val1 == null)
            val1 = 0;

        Integer val2 = map2.get(key);
        if (val2 == null)
            val2 = 0;

        Integer sum = val1 + val2;
        if (sum != 0)
            result.put(key, sum);
    }

    return result;
}
0
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
29 mai 2018 à 11:33
Le "enum" fonctionne mais est plus long pour moi à manipuler, je l'intègrerais dans la 2ème version, je n'ai plus que 2 semaines pour finir la 1ère version.

J'ai étudié la doc de "Map" c'est assez spécial, merci de l'explication qui était très claire, mais je suis un peu bloqué ici, c'est à dire que du coup je suis un peu perdu, perdant la possibilité d'avoir les getters, j'ai essayé pas mal de boucles, en soit il n'y a qu'a remplir la Map des "désignations" puis des "quantité" qui sont toutes deux dans ma classe Outil et incrémenter la quantité, mon IDE veut me faire implémenter les méthodes de la classe Map, je suis un peu perdu encore une fois..

public class CommandeOutils implements Commande
{
    private final  String           next;
    private static FileOutputStream fos;
    private static Row              row;
    private static Cell             cell;

    public static ArrayList<Outil>      outilFirst = new ArrayList<Outil>();
    public SortedSet<Outil>             outilTmp;
    public static ArrayList<Outil>      outil = new ArrayList<Outil>();
    public static Map<String, Integer>  nomQte;

    public CommandeOutils(String next){this.next = next;}

    public String execute(HttpServletRequest req) throws Exception
    {
        readExcel();
        req.setCharacterEncoding("UTF-8");
        req.getServletContext().getRequestDispatcher("/WEB-INF/outils.jsp");
        return next;
    }

    //Compter quantité, calculer différence entre le nombre de "désignation" de différence entre les 2 al

    public void readExcel() throws IOException, InvalidFormatException
    {
        FileInputStream fis = new FileInputStream("C:\\Users\\lomoc\\Cours\\S4\\JSP\\webapps\\Actemium\\WEB-INF\\outillage.xls");
        Workbook wb = WorkbookFactory.create(fis);
        Sheet sh = wb.getSheet("listing");
        int noOfRows = sh.getLastRowNum();
        for (int i = 1; i < noOfRows; i++)
        {
            if (sh.getRow(i) == null)
            {
                out.print("N/A");
                break;
            }
            outilFirst.add(new Outil(
                    sh.getRow(i).getCell(0).toString(), sh.getRow(i).getCell(1).toString(),
                    sh.getRow(i).getCell(2).toString(), sh.getRow(i).getCell(3).toString(),
                    sh.getRow(i).getCell(4).toString(), sh.getRow(i).getCell(5).toString(),
                    sh.getRow(i).getCell(6).toString(), sh.getRow(i).getCell(0).toString(),
                    sh.getRow(i).getCell(8).toString(), sh.getRow(i).getCell(9).toString(),
                    sh.getRow(i).getCell(10).toString(), sh.getRow(i).getCell(11).toString(),
                    sh.getRow(i).getCell(12).toString(), sh.getRow(i).getCell(13).toString(),
                    sh.getRow(i).getCell(14).toString(), sh.getRow(i).getCell(15).toString(),
                    sh.getRow(i).getCell(16).toString(), sh.getRow(i).getCell(17).toString()));

            outilTmp    = new TreeSet<>(outilFirst);    // Passage à un TreeSet pour trier et effacer les doublons
            outil       = new ArrayList<>(outilTmp);    // On repasse à une ArrayList pour pouvoir manipuler facilement
        }
    }

    public static Map<String, Integer> calculQte(String s)
    {
        Map<String, Integer> nomQte = new TreeMap<>();

        for (int i = 0; i < outil.size(); i++)
        {
            nomQte.put(outil.get(i).getDesignation(), outil.get(i).getQuantite());
        }

        Integer qte = ;
        if ()
        return nomQte;
    }
}
0
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
31 mai 2018 à 12:09
Du coup j'appelle les objets dans la JSP en haut de mon fichier avant de commencer n'importe quel traitement :

Map<String, Integer> nomQte = (Map<String, Integer>) request.getAttribute("nomQte");
List<Outil> outils = (ArrayList<Outil>) request.getAttribute("outils");


J'ai rajouté une méthode à ma classe afin de récupérer les désignations de la map, vu que dans l'ArrayList il y a les doublons :

public static Object getKeysFromValue(Map<?, ?> hm, Object value)
    {
        for(Object o: hm.keySet())
        {
            if(hm.get(o).equals(value))
            {
                return o;
            }
        }
        return null;
    }


Je comprends tout ça pas de soucis, mais problème de logique.. Je ne sais pas quoi mettre ici :


public String execute(HttpServletRequest req) throws UnsupportedEncodingException
    {
        ...
        ...
        String designation = getKeysFromValue(nomQte ,                  );

        ...
        ...
        ...
        ...
        return next;
    }


Ou si il y a un moyen plus simple d'afficher parce qu'avoir la valeur en fonction de la clé ça va mais je ne vois qu'à peu près pour clé en fonction de valeur, pour moi la méthode est bonne pour ça je pense.
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
31 mai 2018 à 12:39
Map<?, ?> hm
, c'est quoi les types de tes clés et valeurs ?
Parce que en mettant
?
tu perds tout l'intérêt des types paramétrés...
Et cette nouvelle map contiendra quelles valeurs ?

Le problème en général ici, c'est qu'une valeur peut correspondre à plusieurs clés.
Par exemple si on était encore sur les quantités, tu pourrais avoir plusieurs désignations qui ont des quantités à 1, donc rechercher une désignation par la quantité de l'outil devrait renvoyer 0, 1 ou plusieurs résultats.

Remarque : les EntrySet permettent de simplifier la méthode :

public static <K, V> Set<K> getKeysFromValue(Map<K, V> hm, V value) {
    Set<K> keys = new LinkedHashSet<>();
    for (Entry<K, V> entry : hm.entrySet())
        if (entry.getValue().equals(value))
            keys.add(entry.getKey());
    return keys;
}


Quant aux JSP :

"Pour les out.print c'est comme ça que j'ai appris, des getAttribut en début de fichier, puis des out.print pour le corps de la page"
Je suis d'accord (au niveau débutant) pour mettre des out.print sur la partie dynamique du code.
Cependant pour des gros morceaux de html qui ne changent jamais, il ne devrait plus y avoir de out.print, il faut que tu sortes de ton code Java avec pour rebasculer sur du html et n'y revenir avec
<% %>
qu'au moment opportun.

Ce code là (qui était incorrect, mais peu importe) :
for (int i = 1; i < CommandeOutils.outil.size()/2; i++)
{
    out.print(" <div class=\"tool\">");
    out.print("     <table>");
    out.print("         <ul>");
    out.print("             <li class=\"outil_a\">" + CommandeOutils.outil.get(i).getDesignation() + "</li>");
    out.print("|");
    out.print("             <li class=\"outil_b\">");
    out.print("                 <select class=\"outil_b\">");
    for ( Integer value : CommandeOutils.nomQte.values())
    {
        for (String key : CommandeOutils.nomQte.keySet())
        {
            if (CommandeOutils.outil.get(i).getDesignation().equals(key))
                out.print("<option>" + (value) + "</option>");
        }
    }
    out.print("                 </select>");
    out.print("             </li>");
    out.print("|");
    out.print("             <li class=\"outil_check\">");
    out.print("             <label class=\"label\">");
    out.print("                 <input  class=\"label__checkbox\" type=\"checkbox\" />");
    out.print("                 <span class=\"label__text\">");
    out.print("                     <span class=\"label__check\">");
    out.print("                         <i class=\"fa fa-check icon\"></i>");
    out.print("                     </span>");
    out.print("                 </span>");
    out.print("             </label>");
    out.print("             </li>");
    out.print("         </ul>");
    out.print("     </table>");
    out.print(" </div>");
}

Devrait normalement s'écrire comme ceci dans une JSP :
<% for (int i = 1; i < CommandeOutils.outil.size()/2; i++) { %>
 <div class="tool">
     <table>
         <ul>
             <li class="outil_a"> <%= CommandeOutils.outil.get(i).getDesignation() %></li>
             <li class="outil_b">
                 <select class="outil_b">
<%
    for ( Integer value : CommandeOutils.nomQte.values()) {
        for (String key : CommandeOutils.nomQte.keySet()) {
            if (CommandeOutils.outil.get(i).getDesignation().equals(key)) {
%>
            <option><%= value %></option>
<%}}}%>
                 </select>
             </li>
             <li class="outil_check">
             <label class="label">
                 <input  class="label__checkbox" type="checkbox" />
                 <span class="label__text">
                     <span class="label__check">
                         <i class="fa fa-check icon"></i>
                     </span>
                 </span>
             </label>
             </li>
         </ul>
     </table>
 </div>
<% } %>

C'est plus simple, tu n'as quasiment que du html, sauf à quelques endroits où tu mets du Java.
Alors que toi tu avais du Java qui générait du html, ce qui est le contraire de ce pourquoi est faite la JSP.
0
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
31 mai 2018 à 14:41
Ah ! et bien merci, on n'avait pas su me répondre quand je demandais pourquoi il y avait tant de
out.print
. Merci, je vais volontiers changer ça c'est bien plus agréable à lire et même à coder.

Puis le même problème que j'ai depuis mon dernier message, je ne comprends pas comment utiliser la méthode, du coup je l'ai adaptée à ma Map<String, Integer> :

public static <String, Integer> Set<String> getKeysFromValue(Map<String, Integer> hm, Integer value)
    {
        Set<String> keys = new LinkedHashSet<>();
        for (Map.Entry<String, Integer> entry : hm.entrySet())
            if (entry.getValue().equals(value))
                keys.add(entry.getKey());
        return keys;
    }


J'ai regardé les spécificités des LinkedHashSet et des des Entry c'est ok.
Mon problème ici c'est la compréhension de l'appel et donc de la signature de la méthode :

int quantite = getKeysFromValue(nomQte, );


Je veux préparer la valeur dans ma méthode execute pour la récupérer dans la JSP, sauf que je ne comprends pas quoi mettre et ce que "Integer value" représente dans mon cas.
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
31 mai 2018 à 17:14
Je ne comprends pas ce que tu cherches à faire...

Tu as une map de quantité
[ciseaux=2, marteau=5, tournevis=2]
et la méthode
getKeysFromValue(nomQte, 2)
va te renvoyer
[ciseaux, tournevis]
mais est-ce bien ça que tu veux ? Parce que moi je ne vois pas trop l'intérêt...

Remarque : il ne faut pas mettre
<String, Integer>
dans
public static <String, Integer> Set<String> getKeysFromValue
, moi j'avais mis
<K, V>
c'est à dire des types génériques puisque je ne savais pas ce qu'était K et V puisque tu avais fait
<?, ?>
, mais maintenant qu'on sait que c'est des String et des Integer tu devrais les mettre directement. De plus, vu que les clés sont des String, tu peux te passer du LinkedHashSet et mettre au choix un TreeSet ou un HashSet (j'avais mis LinkedHashSet à cause du type générique K dont je ne savais rien).
0
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
1 juin 2018 à 09:50
Je veux :
- Récupéré le contenu d'un fichier Excel (fait)
- L'organiser, dans la page que j'ai montré en image, avec la designation qui vient du fichier Excel et une quantité que j'ai créé. La quantité est le nombre de "Marteau" par exemple, sauf que dans le fichier Excel il n'y a pas de quantité chaque ligne est un outil unique, ici je veux juste récupérer les désignations sans doublons donc à la place d'avoir dans le fichier excel :

Désignation
____________
Marteau
____________
Marteau
____________
Marteau
____________

Je voudrais sur mon application (comme sur les images présentes sur ce thread) :

Désignation | Quantité
_______________________

Marteau | 3 (Menu déroulant allant de 1 à 3 pour pouvoir faire une demande d'outil selon le besoin)

Pour être plus claire, la quantité est le nombre max d'outils disponibles, libre à l'utilisateur de vouloir 1, 2 ou 3 marteaux. Quantité qui après validation fera l'effet d'un changement dans le fichier Excel, comme une substitution de base de données, c'est pas optimal mais c'est ce qu'on me demande.
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015 > TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
1 juin 2018 à 13:31
Jusque là j'avais compris, et c'est ce qui a été fait (il me semble), avec la Map et la JSP.

Mais pourquoi ce getKeysFromValue ? Cette méthode récupère des outils à partir d'une quantité donnée, dans quel cas tu as besoin de faire ça ?

Si je comprends bien, ce qu'il te manque c'est d'afficher les outils sans doublon.

Une manière de faire (que j'avais déjà proposé plus haut), c'est de gérer tes données dans une
Map<Outil, Integer>
à la place du duo
List<Outil>
+
Map<String,Integer>
.

Autre alternative : faire un duo
Map<String, Outil>
+
Map<String,Integer>
.

Exemple :

private static Map<Outil, Integer> readExcel() {
    Map<Outil, Integer> outils = new TreeMap<>();
    try (FileInputStream fis = new FileInputStream(FILE_NAME); Workbook wb = WorkbookFactory.create(fis)) {
        Sheet sh = wb.getSheet("listing");
        int noOfRows = sh.getLastRowNum();
        for (int i = 1; i < noOfRows; i++) {
            if (sh.getRow(i) == null) {
                throw new IllegalStateException("Row null: " + i);
            }
            Outil outil = new Outil(
                    sh.getRow(i).getCell(0).toString(), sh.getRow(i).getCell(1).toString(),
                    sh.getRow(i).getCell(2).toString(), sh.getRow(i).getCell(3).toString(),
                    sh.getRow(i).getCell(4).toString(), sh.getRow(i).getCell(5).toString(),
                    sh.getRow(i).getCell(6).toString(), sh.getRow(i).getCell(0).toString(),
                    sh.getRow(i).getCell(8).toString(), sh.getRow(i).getCell(9).toString(),
                    sh.getRow(i).getCell(10).toString(), sh.getRow(i).getCell(11).toString(),
                    sh.getRow(i).getCell(12).toString(), sh.getRow(i).getCell(13).toString(),
                    sh.getRow(i).getCell(14).toString(), sh.getRow(i).getCell(15).toString(),
                    sh.getRow(i).getCell(16).toString(), sh.getRow(i).getCell(17).toString());
            outils.merge(outil, outil.getQuantite(), Math::addExact);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return outils;
}

Remarque : ce code nécessite que Outil implements Comparable :

public int compareTo(Outil o) {
    return getDesignation().compareTo(o.getDesignation());
}
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
Modifié le 4 juin 2018 à 15:35
Nickel ça marche bien, merci.

Petit contenu additionnel : J'aimerais simplement faire comme je faisais avec mon ArrayList, une séparation de mes éléments, je m'explique :

Au lieu de faire un affichage de la totalité des outils, par ergonomie visuelle j'aimerais comme précédemment avec l'ArrayList, coupé en 2 colonnes, j'aimerais faire quelque chose comme ça :

for(int i = 0; i < nomQte.size()/2; i++)

for(int i =  nomQte.size()/2; i < nomQte.size(); i++)


Mais en même temps appliquer ça :

for (Map.Entry<String, Integer> entry : nomQte.entrySet())


En réalité je peux le faire, mais une double boucle for n'est pas très esthétique et de toute façon ne marche pas j'imagine avec, j'ai essayé d'imaginer des choses comme ça :

int cptOutils = 1;
for (Map.Entry<String, Integer> entry : nomQte.entrySet())
{
  if (cptOutils > nomQte.size()/2)
    break;
  else
{
Sans succès.
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
4 juin 2018 à 18:05
À ce niveau là, c'est plutôt sur le CSS qu'il faut travailler, pas vraiment sur le Java...

Par exemple
<div style="column-count: 2">
0
TempsMort0 Messages postés 43 Date d'inscription mardi 22 janvier 2013 Statut Membre Dernière intervention 1 août 2018
5 juin 2018 à 09:25
Parfait avec des arrangements, merci pour le temps et les solutions données.
Bonne journée.
0