Double condition pour une double boucle [Résolu]

Double condition pour une double boucle Double boucle Bash (Résolu) » Forum - Shell [PHP] double boucle WHILE mysql_fetch_array (Résolu) » Forum - PHP Variable non stocker dans une double boucle for [Résolu] (Résolu) » Forum - Autoit / batch Excel VBA Sortir de boucle for (Résolu) » Forum - Excel Excel VB: Pbm avec double boucle "For...next& » Forum - VB / VBA

Bonjour,

Petit problème aujourd'hui, en Java EE, j'ai une ArrayList remplie, j'ai tenté de faire une double boucle (ligne 17)
ce qui donne séparément :

for (j = 0; j < conso.size(); j++)
> pour parcourir l'ArrayList

for (i = 65; i <= 90 ; i++ )
> je convertis le résultat en char afin d'afficher l'alphabet à chaque itération, ma condition engendrait un char de base mais j'ai changé pour un int afin de tenter une double boucle.

Je voudrais qu'en dessous des <hr> figurent les éléments à leur lettre correspondante, j'ai tenté :

char lowerAlphabet = Character.toLowerCase((char)i); if (conso.get(i).getDesignation().charAt(0) == ((char)i) || conso.get(i).getDesignation().charAt(0) == lowerAlphabet)
qui n'est peut être pas à changer du coup, vu que ce me semble correct.

Le code en question :
<%     String erreur= (String)request.getAttribute("erreur");     if(erreur!= null)         out.println("<div class=\"messerreur\">"+erreur+"</div>");      List<Consommable> conso = (ArrayList<Consommable>) request.getAttribute("conso"); %>  <div class="middle">     <div class="main_content">         <div class="stock_container">             <p>Yo</p>             <p><%=conso.size()%></p>             <%             int i = 0;             int j = 0;             for (i = 65, j = 0; i <= 90 && j < conso.size(); i++, j++)             {             %>                 <h2><%=((char)i)%></h2>                 <hr>                 <%                     char lowerAlphabet = Character.toLowerCase((char)i);                     if (conso.get(i).getDesignation().charAt(0) == ((char)i) || conso.get(i).getDesignation().charAt(0) == lowerAlphabet)                     {                 %>                     <ul>                         <li><%=conso.get(i).getDesignation()%></li>                     </ul>             <%                     }             }             %>         </div>     </div> </div> 


Merci d'avance

Forum

Double condition pour une double boucle Double boucle Bash (Résolu) » Forum - Shell [PHP] double boucle WHILE mysql_fetch_array (Résolu) » Forum - PHP Variable non stocker dans une double boucle for [Résolu] (Résolu) » Forum - Autoit / batch Excel VBA Sortir de boucle for (Résolu) » Forum - Excel Excel VB: Pbm avec double boucle "For...next& » Forum - VB / VBA

Web: www.shapebootstrap.net

25 réponses

Marsh

NOVEMBER 9, 2013 AT 9:15 PM

Bonjour,

Tu utilises trop les scriptlets(code entre

<% %>
) et pas assez tes classes Java.
La JSP c'est fait pour afficher des données mais les calculs devraient être fait dans des classes.

Ici il te faudrait probablement une méthode dans ton code Java qui ressemblerait à ça :
public static SortedMap<Character, SortedSet<Outil>> sortByInitials(Collection<Outil> outils) {     return outils.stream().collect(Collectors.groupingBy(outil -> Character.toLowerCase(outil.getDesignation().charAt(0)), TreeMap::new, Collectors.toCollection(TreeSet::new))); }

Ta double boucle serait alors quelque chose comme ça :
<% for (Entry<Character, List<Outil>> entry : sortByInitials(outils)) { %>     <h2><%= entry.getKey() %></h2>     <ul>     <% for (Outil outil : entry.getValue()) { %>         <li><%= outil.getDesignation()%></li>     <% } %>     </ul> <% } %>

Remarque : il existe aussi d'autres manières d'écrire des JSP pour supprimer complètement les scriptlets et le code Java. Par exemple avec la JSTL ça ressemblerait à ceci :

<c:forEach var="entry" items="${sortByInitials(outils)}">     <h2><c:out value="${entry.key}"/></h2>     <ul>     <c:forEach var="outil" items="${entry.value}">         <li><c:out value="${outil.designation}"/></li>     </c:forEach>     </ul> </c:forEach>

Reply
réponses:
  • auteur

  • TempsMort0

    Merci pour votre aide encore une fois, j'ai adapté tout ça à mes consommables sans gros succès.
    Je ne comprends pas vraiment dans la méthode sortByInitials ce que symbolise la flèche ici :

    ...(consommable -> Character.toLowerCase(consommable.getDesignation().charAt(0))...

    C'est l'attribution à "consommable" qui est une valeur générique ?

    Can only iterate over an array or an instance of java.lang.Iterable > Erreur tomcat
    foreach not applicable to type 'java.util.SortedMap<java.lang.Character,java.util.SortedSet<pac.bdd.beans.Consommable>>' > Erreur IDE (Intellij)

    L'import de la servlet :
     List<Consommable> conso = (ArrayList<Consommable>) request.getAttribute("conso");


    <% for (Map.Entry<Character, List<Consommable>> entry : sortByInitials(conso)) { %>   <h2><%= entry.getKey() %></h2>     <ul>       <% for (Consommable consommable : entry.getValue()) { %>          <li><%= consommable.getDesignation()%></li>       <% } %>     </ul> <% } %>


    package pac.cmd;  import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import pac.bdd.beans.Consommable;  import javax.servlet.http.HttpServletRequest; import java.io.FileInputStream; import java.io.UnsupportedEncodingException; import java.util.*; import java.util.stream.Collectors;  public class CommandeStock implements Commande {     private static final String STOCK_FILE_NAME = "C:\\Users\\lomoc\\Cours\\S4\\JSP\\webapps\\Actemium\\WEB-INF\\stock.xls";      private final String next;      public CommandeStock(String next)     {         this.next = next;     }      public String execute(HttpServletRequest req) throws UnsupportedEncodingException     {         List<Consommable> conso = readExcelStock();          req.setAttribute("conso", conso);         req.setCharacterEncoding("UTF-8");         req.getServletContext().getRequestDispatcher("/WEB-INF/stock.jsp");         return next;     }      private static List<Consommable> readExcelStock()     {         List<Consommable> conso = new ArrayList<>();         try (FileInputStream fis = new FileInputStream(STOCK_FILE_NAME); Workbook wb = WorkbookFactory.create(fis))         {             Sheet sh = wb.getSheet("STOCK");             int noOfRows = sh.getLastRowNum();              for (int i = 1; i < noOfRows; i++)             {                 if (sh.getRow(i) == null)                 {                     throw new IllegalStateException("Row null: " + i);                 }                 conso.add(new Consommable(                         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()));             }         } catch (Exception e)         {             e.printStackTrace();         }         return conso;     }      public static SortedMap<Character, SortedSet<Consommable>> sortByInitials(Collection<Consommable> conso)     {         return conso.stream().collect(Collectors.groupingBy(consommable -> Character.toLowerCase(consommable.getDesignation().charAt(0)), TreeMap::new, Collectors.toCollection(TreeSet::new)));     } } 


    Et oui les variables de ma classe Consommable sont comme précédemment que des String, j'arrangerais ça quand j'aurais plus de temps.

  • KX

    • "Je ne comprends pas vraiment dans la méthode sortByInitials"

    Je ne m'attendais pas vraiment à ce que tu la comprennes, l'important ici c'était surtout de te donner une idée de la signature de la méthode pour faire la correspondance avec son utilisation dans la JSP.
    Mais si tu ne comprends pas ce mon code, il y a d'autres manière d'écrire cette méthode.

    Pour comprendre : le premier paramètre de Collectors.groupingBy c'est une fonction qui permet de calculer la clé de la Map dans laquelle on va mettre l'objet. Ici c'est donc le calcul de l'initiale de sa désignation, sur le même principe que le
    conso.get(i).getDesignation().charAt(0)
    que tu avais proposé.

    "consommable", qui est avant la flèche, correspond au paramètre de la méthode. C'est pareil que faire :
    public static char getInitiale(Consommable consommable) {     return Character.toLowerCase(consommable.getDesignation().charAt(0)); }

    Remarque : si tu écris la méthode à côté (conseillé), dans ce cas on pourrait faire une référence de méthode à la place de l'expression lambda.

    Collectors.groupingBy(CommandeStock::getInitiale, ...)

     
    • "Can only iterate over an array or an instance of java.lang.Iterable"

    En effet, j'en ai oublié une petite partie (je code de tête, sans tester...)

    Comme pour les codes précédents, il faut utiliser la méthode entrySet() pour passer de la Map au Set<Entry>
    for (Entry<Character, List<Consommable>> entry : sortByInitials(conso).entrySet())

  • TempsMort0

    La condition :

    for (Map.Entry<Character, List<Consommable>> entry : sortByInitials(conso).entrySet())

    ne marche pas, la List gêne, la méthode Entry attend que le 2ème élement ne soit pas une List mais un SortedSet :
    for (Map.Entry<Character, SortedSet<Consommable>> entry : sortByInitials(conso).entrySet())

    Je ne sais pas si c'est la meilleure idée, je vais essayer de faire marcher ça.

  • KX

    Oui, c'est un SortedSet... c'est normal. On a une SortedMap<Character, SortedSet<Consommable>> donc on doit avoir un Entry<Character, SortedSet<Consommable>>

    Sauf que dans une première version du code j'avais Map<Character, List<Outil>> (qui perdait l'ordre) et quand j'ai changé le code Java j'ai oublié de changer le code de la JSP... (problèmes qui n'arriveraient pas avec la JSTL)

  • TempsMort0

    J'ai un "out of bounds : String index out of range: 0"

    Soit cet import ne suffit pas :

    List<Consommable> conso = (List<Consommable>) request.getAttribute("conso");

    Mais vu que j'appelle la méthode sortByInitials dans la JSP j'imagine que ce n'est pas le problème.

    Soit la boucle est mauvaise mais il n'y a pas de raison :

    <% for (SortedMap.Entry<Character, SortedSet<Consommable>> entry : sortByInitials(conso).entrySet())    { %>       <h2><%= entry.getKey() %></h2>          <ul>             <% for (Consommable consommable : entry.getValue())                   { %>                          <li><%= consommable.getDesignation()%></li>              <% } %>          </ul> <% } %>


    ça doit être au remplissage que le problème réside :

    public static SortedMap<Character, SortedSet<Consommable>> sortByInitials(Collection<Consommable> conso) {         return conso.stream().collect(Collectors.groupingBy(consommable ->          Character.toLowerCase(consommable.getDesignation().charAt(0)), TreeMap::new,          Collectors.toCollection(TreeSet::new))); } 


    Je pense déjà pouvoir mettre "List" dans la signature à la place de "Collection" mais ça n'arrangera pas le problème, mais après le doute s'installe.

  • KX

    "out of bounds : String index out of range: 0"
    C'est le charAt(0) qui plante car tu as une désignation vide

    ""
    , il faudrait gérer ce cas particulier, parce que sans désignation tu ne peut pas en déterminer l'initiale...

  • TempsMort0

    Désolé le débogage est compliqué, les solutions qui me paraissent logiques ne fonctionnent pas, je suis passé par la JSP mais comme vous m'avez précisé, ça se fait dans le Java du coup, j'avais rajouté une méthode qui au final se révélait peu utile. Mon idée ici est simple, ligne 11 je me suis dis "Si la case des désignations est vide, alors on passe la ligne", sans succès, la même erreur apparaît..

    private static List<Consommable> readExcelStock()     {         List<Consommable> conso = new ArrayList<>();         try (FileInputStream fis = new FileInputStream(STOCK_FILE_NAME); Workbook wb = WorkbookFactory.create(fis))         {             Sheet sh = wb.getSheet("STOCK");             int noOfRows = sh.getLastRowNum();              for (int i = 1; i < noOfRows; i++)             {                 if (sh.getRow(i).getCell(0).toString() == null) continue;                 conso.add(new Consommable(                         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()));             }         } catch (Exception e)         {             e.printStackTrace();         }         return conso;     }

  • KX

    La méthode

    toString()
    ne renverra jamais null, donc un test
    toString() == null
    n'est pas pertinent, il faudrait plutôt regarder si la chaîne de caractères est vide.

    Row row = sh.getRow(i); String designation = row.getCell(0).getStringCellValue(); if (designation.isEmpty())      continue;

    Remarque : c'est le genre de contrôles qui pourraient être déportés dans une autre partie du code, par exemple dans le constructeur de Consommable :

    public Consommable(String designation, ...) {     if (designation == null || designation.isEmpty())         throw new IllegalArgumentException("designation is empty");     ... }

    try {     conso.add(new Consommable(row.getCell(0).getStringCellValue(), ...); } catch (Exception e) {     System.err.println("Warning. Can't parse line " + i  + ". " + e); }

Marsh

NOVEMBER 9, 2013 AT 9:15 PM

Mmh maintenant la List conso ne contient plus que 2 éléments, alors que le fichier en contient 379 en comptant seulement les items.



On peut voir de quoi est remplie la List :



Désolé pour ces posts longs mais je suis perdu sur ce coup, je peux faire des tests pour mener à trouver des solutions.. parce que là je ne vois pas..


<%@ page import="pac.bdd.beans.Consommable" %> <%@ page import="pac.cmd.CommandeStock" %> <%@ page import="static pac.cmd.CommandeStock.sortByInitials" %> <%@ page import="java.util.*" %> <%@include file="../ihm/miseEnPage1.jsp" %> <%@ page contentType="text/html; charset=UTF-8" %>  <%     String erreur= (String)request.getAttribute("erreur");     if(erreur!= null)         out.println("<div class=\"messerreur\">"+erreur+"</div>");      List<Consommable> conso = (List<Consommable>) request.getAttribute("conso"); %>  <div class="middle">     <div class="main_content">         <div class="stock_container">             <p><%=conso.size()%></p>             <% for (Map.Entry<Character, SortedSet<Consommable>> entry : sortByInitials(conso).entrySet())             {             %>             <h2><%= entry.getKey() %></h2>             <ul>                 <% for (Consommable consommable : entry.getValue())                    {                 %>                 <li><%= consommable.getDesignation()%></li>                 <% } %>             </ul>             <% } %>         </div>     </div> </div> <jsp:include page="../ihm/miseEnPage2.jsp" />



package pac.cmd;  import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import pac.bdd.beans.Consommable;  import javax.servlet.http.HttpServletRequest; import java.io.FileInputStream; import java.io.UnsupportedEncodingException; import java.util.*; import java.util.stream.Collectors;  public class CommandeStock implements Commande {     private static final String STOCK_FILE_NAME = "C:\\Users\\lomoc\\Cours\\S4\\JSP\\webapps\\Actemium\\WEB-INF\\stock.xls";      private final String next;      public CommandeStock(String next)     {         this.next = next;     }      public String execute(HttpServletRequest req) throws UnsupportedEncodingException     {         List<Consommable> conso = readExcelStock();          req.setAttribute("conso", conso);         req.setCharacterEncoding("UTF-8");         req.getServletContext().getRequestDispatcher("/WEB-INF/stock.jsp");         return next;     }      private static List<Consommable> readExcelStock()     {         List<Consommable> conso = new ArrayList<>();         try (FileInputStream fis = new FileInputStream(STOCK_FILE_NAME); Workbook wb = WorkbookFactory.create(fis))         {             Sheet sh = wb.getSheet("STOCK");             int noOfRows = sh.getLastRowNum();              for (int i = 1; i < noOfRows; i++)             {                 Row row = sh.getRow(i);                 String designation = row.getCell(0).getStringCellValue();                 if (designation.isEmpty())                     continue;                 conso.add(new Consommable(                         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()));             }         } catch (Exception e)         {             e.printStackTrace();         }         return conso;     }      public static SortedMap<Character, SortedSet<Consommable>> sortByInitials(List<Consommable> conso)     {         return conso.stream().collect(Collectors.groupingBy(consommable -> Character.toLowerCase(consommable.getDesignation().charAt(0)), TreeMap::new, Collectors.toCollection(TreeSet::new)));     } }

Reply
réponses:
  • auteur

  • KX

    Dans la mesure où ton code est dans le Java (et pas dans la JSP) tu peux faire un main() et tester en local, avec des println en plus si besoin. Tu peux aussi mettre des points de debug et faire du pas à pas.

    public static void main(String[] args) {     List<Consommable> list = readExcelStock();     System.out.println(list.size()); // 379 ?     System.out.println(list);     SortedMap<Character, SortedSet<Consommable>> map = sortByInitials(list);     System.out.println(map.size()); // <= 26     System.out.println(map); }

  • TempsMort0

    Yes, j'ai déjà rajouté ce main, enlevé le simple if, j'ai mis en place le try catch de votre message de ce matin :

    Résultat pour la liste :

    Warning. Can't parse line 6. java.lang.NullPointerException
    Warning. Can't parse line 387. java.lang.NullPointerException
    //Pareil de 388 à 409...
    Warning. Can't parse line 410. java.lang.NullPointerException
    417
    //Toutes les valeurs sous forme d'adresse


    Résultat pour le SortedMap (normalement à la suite) :

    Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
    at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:44)
    at java.base/java.lang.String.charAt(String.java:704)
    at pac.cmd.CommandeStock.lambda$sortByInitials$0(CommandeStock.java:72)
    at java.base/java.util.stream.Collectors.lambda$groupingBy$49(Collectors.java:1075)
    at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1494)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:511)
    at pac.cmd.CommandeStock.sortByInitials(CommandeStock.java:72)
    at pac.cmd.CommandeStock.main(CommandeStock.java:81)


    Je ne comprends pas que faire quelque chose d'aussi simple soit si tricky, traiter du fichier .txt, .csv n'a rien de problématique... Je n'ai jamais pris autant de temps avec cette api Apache pour afficher des données en fonction d'un tri banal..

  • KX

    Donc le problème c'est le NullPointerException, une vraie erreur dont il va falloir regarder le détail (e.printStackTrace) car j'avais mis ce code là pour les IllegalArgumentException (des warning) que l'on aurait mis dans le constructeur mais ici c'est autre chose.

    Evidemment il faudra regarder en parallèle de l'erreur à quoi correspondent dans le fichier Excel les lignes indiquées.

    try {     conso.add(...) } catch (Exception e) {     System.err.println("Can't parse line " + i  + " :  ");     e.printStackTrace(); }

  • TempsMort0

    J'ai beau cherché toute l'après-midi, je tourne en rond..

    J'ai printStackTrace :

    java.lang.NullPointerException
    at pac.cmd.CommandeStock.readExcelStock(CommandeStock.java:52)
    at pac.cmd.CommandeStock.main(CommandeStock.java:77)


    J'ai 417 valeurs dans la List, les éléments s'affichent sous forme d'adresse car le toString est manquant mais ça ce n'est rien. Impossible de trouver comment régler ça..

    package pac.cmd;  import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import pac.bdd.beans.Consommable;  import javax.servlet.http.HttpServletRequest; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.*; import java.util.stream.Collectors;  public class CommandeStock implements Commande {     private static final String STOCK_FILE_NAME = "C:\\Users\\lomoc\\Cours\\S4\\JSP\\webapps\\Actemium\\WEB-INF\\stock.xls";      private final String next;      public CommandeStock(String next)     {         this.next = next;     }      public String execute(HttpServletRequest req) throws IOException, InvalidFormatException     {         List<Consommable> conso = readExcelStock();          req.setAttribute("conso", conso);         req.setCharacterEncoding("UTF-8");         req.getServletContext().getRequestDispatcher("/WEB-INF/stock.jsp");         return next;     }      private static List<Consommable> readExcelStock() throws IOException, InvalidFormatException     {         List<Consommable> conso = new ArrayList<>();         try (FileInputStream fis = new FileInputStream(STOCK_FILE_NAME); Workbook wb = WorkbookFactory.create(fis))         {             Sheet sh = wb.getSheet("STOCK");             int noOfRows = sh.getLastRowNum();              for (int i = 1; i < noOfRows; i++)             {                 try                 {                     conso.add(new Consommable(                             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()));                 }                 catch (NullPointerException e)                 {                     e.printStackTrace();                 }             }         }         return conso;     }      public static SortedMap<Character, SortedSet<Consommable>> sortByInitials(List<Consommable> conso)     {         return conso.stream().collect(Collectors.groupingBy(consommable -> Character.toLowerCase(consommable.getDesignation().charAt(0)), TreeMap::new, Collectors.toCollection(TreeSet::new)));     }      public static void main(String[] args) throws IOException, InvalidFormatException     {         List<Consommable> list = readExcelStock();         System.out.println(list.size()); // 379 ?         System.out.println(list.toString());          SortedMap<Character, SortedSet<Consommable>> map = sortByInitials(list);         System.out.println(map.size()); // <= 26         System.out.println(map);     } } 

  • KX

    D'après la documentation, getCell(n) peut renvoyer null, ce qui explique que le toString plante.
    https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Row.html#getCell-int-

    Essayes ceci :

    public static String getCellAsString(Sheet sheet, int rownum, int cellnum) {     Row row = sheet.getRow(rownum);     if (row == null)  {         System.err.println("Warning: row undefined: " + rownum);         return "";     }      Cell cell = row.getCell(cellnum);     if (cell == null) {         System.err.println("Warning: on row " + rownum +" cell undefined: " + cellnum);         return "";     }      return cell.toString(); }

    conso.add(new Consommable(getCellAsString(sh, i, 0), getCellAsString(sh, i, 1), getCellAsString(sh, i, 2), ... 

  • TempsMort0

    Merci pour ça, les Warning sont très utiles, j'ai reformaté le fichier Excel de base car j'ai maintenant le droit d'écriture, il pouvait y avoir des sommes en fin de fichier, ce genre de choses qui pouvait gêner, du coup parfait, ma List est remplie de tous les éléments (381) parcontre dans mon SortedSet je n'ai que 19 valeurs car la méthode "sortByInitials" à l'air d'associer un Consommable par initial, soit le premier qu'il voit :



    J'aimerais que tous les Consommables commençant par la lettre A soient sous la même lettre A, tous les consommables B sous une seule lettre B, ainsi de suite.. j'ai essayé de boucler, puis de la reprendre entièrement, la méthode sortByInitials, sans succès. A moins que la méthode ne corresponde pas a l'objectif donné ?

    public static SortedMap<Character, SortedSet<Consommable>> sortByInitials(List<Consommable> conso) {     return conso.stream().collect(Collectors.groupingBy(consommable -> Character.toLowerCase(consommable.getDesignation().charAt(0)), TreeMap::new, Collectors.toCollection(TreeSet::new))); }

  • KX

    sortByInitials fait ceci :

    [Pomme, Abricot, Orange, Poire] → [a=[Abricot], o=[Orange], p=[Poire, Pomme]] 

    Mais si tu n'as qu'un seul élément dans chacun des groupes cela peut venir d'une mauvaise implémentation de la méthode
    Consommable.compareTo
    qui considérerait que tous les objets sont égaux (renvoie tout le temps 0) et donc au moment du tri on ne garderait qu'une seule valeur dans chaque TreeSet.

  • KX

    Remarque : voici une autre manière de coder sortByInitials, le résultat sera exactement le même, mais tu comprendras peut-être mieux comme ça :

    public static SortedMap<Character, SortedSet<Consommable>> sortByInitials(List<Consommable> consommables) {     SortedMap<Character, SortedSet<Consommable>> result = new TreeMap<>();     for (Consommable consommable : consommables) {         char lowerInitial = Character.toLowerCase(consommable.getDesignation().charAt(0));         SortedSet<Consommable> consommablesForInitial = result.get(lowerInitial);         if (consommablesForInitial == null) {             consommablesForInitial = new TreeSet<>();             result.put(lowerInitial, consommablesForInitial);         }         consommablesForInitial.add(consommable);     }     return result; }

  • TempsMort0

    Effectivement j'ai laissé "return 0;" dans cette méthode.

    Les données stockées dans un TreeSet sont représentées dans la TreeMap et je vois "triées selon leurs valeurs" je comprends de façon logique, en fait je ne comprends pas de quoi j'ai besoin dans mon compareTo, autant je voyais pour ma classe Outil, vu qu'on comparait les désignations pour enlever les doublons :

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


    Autant ici, la conception sur ce point est flou dans ma tête.

    Edit : Merci pour la méthode, c'est moins modulaire, mais je comprends tout ^^

  • KX

    Le compareTo doit renvoyer une valeur négative, positive ou nulle pour indiquer si l'objet courant (this) est plus petit, plus grand, ou égal à l'objet passé en paramètre.

    On pourrait considérer que pour un Consommable c'est comme un Outil et que la désignation est suffisante pour le tri, dans ce cas la méthode compareTo serait la même pour Consommable qu'elle ne l'était pour Outil.

    Une autre manière de concevoir les choses (à toi de voir), c'est de considérer qu'un Consommable n'est pas triable "dans l'absolu", c'est à dire que la classe Consommable n'implémente pas Comparable.
    Et c'est uniquement quand on en aura besoin (par exemple dans la méthode sortByInitial) où on lui indiquera un Comparator spécifique pour le TreeSet utilisé, ce qui permettra de faire différents types de tris différents.
    Un bon compromis étant d'avoir une méthode de tri par défaut (Comparable sur la désignation, comme Outil) tout en s'autorisant à utiliser d'autres Comparator ponctuellement.

  • TempsMort0

    Je ne comprends pas, je repasse le code depuis hier, ça ne vient pas du CompareTo qui est fonctionnel.
    (C'est comme prévu le même que celui des outils pour les consommables)

    Je n'arrive pas à afficher tous les consommables en fonction de leur lettre référente..
    Auriez-vous une idée ? Merci d'avance

  • KX

    Est-ce que tu as réussi à faire fonctionner en local un petit code de test qui calcule tes groupes par initiale de consommables comme dans cet exemple ?

    [Pomme, Abricot, Orange, Poire] → [a=[Abricot], o=[Orange], p=[Poire, Pomme]]

    Si oui, c'est uniquement un problème dans l'affichage côté JSP, si non il faut d'abord revoir la partie algorithmique avant de faire un quelconque affichage...

  • TempsMort0

    J'ai réalisé les tests au préalable, l'affichage paraissait bon j'ai vérifié également.

    Toujours vérifier que les fichiers externes au code sont bien formatés, le fichier Excel visé comportait des irrégularités, l'affichage est presque parfait.

    Du coup, dernière question, y aurait-il un moyen de récupérer le résultat d'une cellule plutôt que de refaire les calculs dans le code ? C'est à dire que certaines cellules possèdent des formules, et ce sont les formules qui sont stockées.
    (L'API qui gère ça est "POI" une API d'Apache, et ne comporte pas de méthode pour le faire)

  • KX

    "L'API qui gère ça est "POI" une API d'Apache, et ne comporte pas de méthode pour le faire"
    Je ne connais pas bien cette API, mais getCellFormula() semble prévu pour faire ça...
    https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#getCellFormula--

  • TempsMort0

    C'est moi qui ait été bête. C'est vrai que cette
    API n'est jamais utilisée.. Dans la classe Consommable j'ai changé la variable voulue en double vu qu'elle était en int et à la base en String , je réfléchissais dans le mauvais sens c'était un entier dans l'Excel mais la signature de getCellFormula retourne un double. Il est donc facile après d'afficher le résultat.

    Merci pour l'aide, merci pour l'aide globale sur le forum, super boulot, bonne continuation. :)

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed