Menu

Double condition pour une double boucle [Résolu]

TempsMort0 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 5 juin 2018 à 17:14 - Dernière réponse : TempsMort0 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention
- 14 juin 2018 à 18:04
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
Afficher la suite 

Votre réponse

25 réponses

KX 15681 Messages postés samedi 31 mai 2008Date d'inscriptionModérateurStatut 19 août 2018 Dernière intervention - Modifié par KX le 5/06/2018 à 20:43
0
Merci
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>
KX 15681 Messages postés samedi 31 mai 2008Date d'inscriptionModérateurStatut 19 août 2018 Dernière intervention > TempsMort0 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 6 juin 2018 à 15:23
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 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 6 juin 2018 à 15:54
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 15681 Messages postés samedi 31 mai 2008Date d'inscriptionModérateurStatut 19 août 2018 Dernière intervention > TempsMort0 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 6 juin 2018 à 16:12
"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 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 6 juin 2018 à 17:35
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 15681 Messages postés samedi 31 mai 2008Date d'inscriptionModérateurStatut 19 août 2018 Dernière intervention > TempsMort0 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 6 juin 2018 à 18:00
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);
}
Commenter la réponse de KX
TempsMort0 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 7 juin 2018 à 12:51
0
Merci
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)));
    }
}
TempsMort0 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 12 juin 2018 à 16:50
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 15681 Messages postés samedi 31 mai 2008Date d'inscriptionModérateurStatut 19 août 2018 Dernière intervention > TempsMort0 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 12 juin 2018 à 18:18
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 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 14 juin 2018 à 09:31
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 15681 Messages postés samedi 31 mai 2008Date d'inscriptionModérateurStatut 19 août 2018 Dernière intervention > TempsMort0 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 14 juin 2018 à 13:32
"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 43 Messages postés mardi 22 janvier 2013Date d'inscription 1 août 2018 Dernière intervention - 14 juin 2018 à 18:04
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. :)
Commenter la réponse de TempsMort0