IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Disparition d'objets dans des TreeMap


Sujet :

Langage Java

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Disparition d'objets dans des TreeMap
    Bonjour,

    J'ai un problème assez gênant: je perd des données... Je m'explique mais c'est un peu long .

    J'ai des TypeMesure qui contienent des Mesures qui sont liées à des DateMesures, des ProfondeurMesure, des PositionMesure et un paramètre physique.
    Les TypeMesure ont aussi 2 attributs qui me servent par la suite (numéro de cast et numéro de station).

    Or j'ai besoin d'imprimer les mesures par ordre de date, puis de position et ainsi de suite dans un fichier. Mes données étant dans une base de données (Postgre) avec hybernate/spring au milieu.
    Donc le service web me donne tous les TypeMesure (une List en fait) qu'il souhaite imprimer et moi je me débrouille.

    Voilà à quoi ressemble le code de la méthode principale:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    /**
     * Ecrit l'ensemble des données dans le fichier.
     * 
     * @param typeMesure les type mesure à ecrire.
     * @throws IOException si problème avec les fichiers
     */
    void writeData(List<TypeMesure> typeMesure) throws IOException {
    	TreeMap<DateMesure,
    		TreeMap<PositionMesure,
    			TreeMap<ProfondeurMesure,
    				TreeMap<Integer,
    					TreeMap<Integer,
    						TreeMap<ParametrePhysique, Mesure>>>>>> map = prepareData(typeMesure);
     
    	boolean writeFirstLine = true;
     
    	// on iter sur la map pour savoir ce qu'on écrit ou pas
    	for (DateMesure dateMesure : map.navigableKeySet()) {
    		TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>> treeMapDateMesure = map
    			.get(dateMesure);
    		for (PositionMesure positionMesure : treeMapDateMesure
    			.navigableKeySet()) {
    			TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>> treeMapPositionMesure = treeMapDateMesure
    				.get(positionMesure);
    			// /!\ BUG
    			// treeMapPositionMesure peut être null ici 
    			// /!\ BUG
    			for (ProfondeurMesure profondeurMesure : treeMapPositionMesure
    				.navigableKeySet()) {
    				TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>> treeMapProfondeurMesure = treeMapPositionMesure
    					.get(profondeurMesure);
    				for (Integer castCourrant : treeMapProfondeurMesure
    					.navigableKeySet()) {
    					TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>> treeMapCastCourrant = treeMapProfondeurMesure
    						.get(castCourrant);
    					for (Integer stationCourrant : treeMapCastCourrant
    						.navigableKeySet()) {
     
    						// on imprime les données
    						// mais c'est pas le problème
    						if (writeFirstLine) {
    							writeFirstLine = false;
    						}
     
    					}
    				}
    			}
    		}
    	}
    }
    La méthode prepareData (qui construit la map de maps)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    /**
     * Prépare les données sous une forme plus manipulable par la suite.
     * 
     * @param typeMesureList la liste des type mesure à manipuler
     * @return la map
     */
    TreeMap<DateMesure, TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>> prepareData(
    		List<TypeMesure> typeMesureList) {
    	// On commence par trier les donner dans des liste (pour les éléments
    	// commun) et dans une map pour toutes les mesures qu'on pourrai
    	// rencontrer.
    	// DateMesure -> PositionMesure -> ProfondeurMesure -> NumCast ->
    	// NumStation -> ParamPhy -> Mesure
    	TreeMap<DateMesure, TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>> map = new TreeMap<DateMesure, TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>>(
    		COMPARATOR_DATE_MESURE);
     
    	for (TypeMesure typeMesure : typeMesureList) {
    		Set<Mesure> mesureSet = typeMesure.getMesureSet();
    		// on récupère les numéros cast et numéros station si on les as
    		Integer currentCast = null;
    		Integer currentStation = null;
    		// le code a été enlevé pour la lisibilité
    		// il ne manipule pas l'objet map ni les mesure il ne touche qu'aux currentCast, currentStation et typeMesure
     
    		for (Mesure mesure : mesureSet) {
    			ParametrePhysique parametrePhysique = mesure
    				.getParametrePhysique();
    			// le code important est ici !
    			TreeMap<ParametrePhysique, Mesure> treeMapStation = getLastSubMap(
    				map, currentCast, currentStation, mesure);
     
    			// enfin on stock le paramètre
    			treeMapStation.put(parametrePhysique, mesure);
    		}
    		debugPrintMap(map, "Map for: " + typeMesure.toString());
    	}
     
    	debugPrintMap(map, "First Map");
     
    	return map;
    }
    La méthode qui construit les map intermédiaires si besoin, et retourne la dernière map, là où sont ajoutée les données.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    /**
     * Retourne la sous map nécessaire au stockage de la mesure
     * 
     * @param map la map global
     * @param currentCast le numéro cast courrant
     * @param currentStation le numéro station courrant
     * @param mesure la mesure à stocker (n'est pas stockée dans la map!)
     * @return la map dans laquelle on stock la donnée
     */
    TreeMap<ParametrePhysique, Mesure> getLastSubMap(
    		TreeMap<DateMesure, TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>> map,
    		Integer currentCast, Integer currentStation, Mesure mesure) {
    	DateMesure dateMesure = mesure.getDateMesure();
    	PositionMesure positionMesure = mesure.getPositionMesure();
    	ProfondeurMesure profondeurMesure = mesure.getProfondeurMesure();
     
    	// on crée la sous map pour la date si elle n'existe pas
    	if (!map.containsKey(dateMesure)) {
    		map.put(
    				dateMesure,
    				new TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>(
    					COMPARATOR_POSITION_MESURE));
    	}
    	TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>> treeMapDateMesure = map
    		.get(dateMesure);
     
    	if (!treeMapDateMesure.containsKey(positionMesure)) {
    		treeMapDateMesure.put(
    				positionMesure,
    				new TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>(
    					COMPARATOR_PROFONDEUR_MESURE));
    	}
    	TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>> treeMapPositionMesure = treeMapDateMesure
    		.get(positionMesure);
     
    	if (!treeMapPositionMesure.containsKey(profondeurMesure)) {
    		treeMapPositionMesure.put(
    				profondeurMesure,
    				new TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>(
    					COMPARATOR_INTEGER));
    	}
    	TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>> treeMapProfondeurMesure = treeMapPositionMesure
    		.get(profondeurMesure);
     
    	if (!treeMapProfondeurMesure.containsKey(currentCast)) {
    		treeMapProfondeurMesure.put(currentCast,
    			new TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>(
    				COMPARATOR_INTEGER));
    	}
    	TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>> treeMapCast = treeMapProfondeurMesure
    		.get(currentCast);
     
    	if (!treeMapCast.containsKey(currentStation)) {
    		treeMapCast.put(currentStation,
    			new TreeMap<ParametrePhysique, Mesure>(COMPARATOR_PARAM_PHY));
    	}
    	TreeMap<ParametrePhysique, Mesure> treeMapStation = treeMapCast
    		.get(currentStation);
     
    	return treeMapStation;
    }
    Les comparator utilisés pour les TreeMap:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
     
    private final class DateMesureComparator implements Comparator<DateMesure> {
    	/** {@inheritDoc} */
    	@Override
    	public int compare(DateMesure o1, DateMesure o2) {
    		int result = o1.getDate().compareTo(o2.getDate());
    		if (result == 0) {
    			// les valeurs sont identiques mais ce ne sont peut-être pas les
    			// même dates
    			int o1Id = o1.getId();
    			int o2Id = o2.getId();
    			if (o1Id < o2Id) {
    				result = -1;
    			} else if (o1Id > o2Id) {
    				result = 1;
    			}
    		}
    		return result;
    	}
    }
     
    private final class ProfondeurMesureComparator implements
    		Comparator<ProfondeurMesure> {
    	/** {@inheritDoc} */
    	@Override
    	public int compare(ProfondeurMesure o1, ProfondeurMesure o2) {
    		float o1Prof = o1.getProfondeur();
    		float o2Prof = o2.getProfondeur();
    		int result = 0;
    		if (o1Prof < o2Prof) {
    			result = -1;
    		} else if (o1Prof > o2Prof) {
    			result = 1;
    		}
    		if (result == 0) {
    			// les profondeur sont peut-être identique en valeur mais pas en
    			// ID
    			int o1Id = o1.getId();
    			int o2Id = o2.getId();
    			if (o1Id < o2Id) {
    				result = -1;
    			} else if (o1Id > o2Id) {
    				result = 1;
    			}
    		}
    		return result;
    	}
    }
     
    private final class PositionMesureComparator implements
    		Comparator<PositionMesure> {
     
    	/** {@inheritDoc} */
    	@Override
    	public int compare(PositionMesure o1, PositionMesure o2) {
    		float o1Lat = o1.getLatitude();
    		float o1Long = o1.getLongitude();
    		float o2Lat = o2.getLatitude();
    		float o2Long = o2.getLongitude();
     
    		int result = 0;
     
    		if (o1Lat == o2Lat) {
    			if (o1Long < o2Long) {
    				result = -1;
    			} else if (o1Long > o2Long) {
    				result = 1;
    			}
    		} else if (o1Lat < o2Lat) {
    			result = -1;
    		} else if (o1Lat > o2Lat) {
    			result = 1;
    		}
     
    		if (result == 0) {
    			int o1Id = o1.getId();
    			int o2Id = o2.getId();
    			if (o1Id < o2Id) {
    				result = -1;
    			} else if (o1Id > o2Id) {
    				result = 1;
    			}
    		}
     
    		return result;
    	}
    }
     
    private final class IntegerComparator implements Comparator<Integer> {
    	/** {@inheritDoc} */
    	@Override
    	public int compare(Integer o1, Integer o2) {
    		if (o1 == null && o2 == null) {
    			return 0;
    		}
    		if (o1 == null && o2 != null) {
    			return -1;
    		}
    		if (o1 != null && o2 == null) {
    			return 1;
    		}
    		return o1.compareTo(o2);
    	}
    }
     
    private final class ParametrePhysiqueComparator implements
    		Comparator<ParametrePhysique> {
    	/** {@inheritDoc} */
    	@Override
    	public int compare(ParametrePhysique o1, ParametrePhysique o2) {
    		// on compare les chaines de caractère des différents code
    		return o1.getCodeRoscop().compareTo(o2.getCodeRoscop());
    	}
    }
     
    private final Comparator<DateMesure> COMPARATOR_DATE_MESURE = new DateMesureComparator();
    private final Comparator<ProfondeurMesure> COMPARATOR_PROFONDEUR_MESURE = new ProfondeurMesureComparator();
    private final Comparator<PositionMesure> COMPARATOR_POSITION_MESURE = new PositionMesureComparator();
    private final Comparator<Integer> COMPARATOR_INTEGER = new IntegerComparator();
    private final Comparator<ParametrePhysique> COMPARATOR_PARAM_PHY = new ParametrePhysiqueComparator();
    Les méthodes utilisées pour imprimer une map:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
    	protected void debugPrintMap(Map map, String header) {
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
    		File file = new File("D:\\testMap" + sdf.format(new Date()));
    		try {
    			DataOutputStream out = new DataOutputStream(new FileOutputStream(
    				file));
     
    			out.writeBytes(header);
    			out.writeBytes("\n");
     
    			debugPrintMap(map, out);
     
    			out.flush();
    			out.close();
    		} catch (Exception e) {
    			LOG.debug("aie...");
    			e.printStackTrace();
    		}
    	}
     
    	protected void debugPrintMap(Map map, DataOutputStream out2)
    			throws IOException {
    		debugPrintMap(map, out2, 0);
    	}
     
    	protected void debugPrintMap(Map map, DataOutputStream out2, int level)
    			throws IOException {
    		int nextLevel = level + 1;
    		out2.writeBytes("{\n");
    		for (Object key : map.keySet()) {
    			Object value = map.get(key);
     
    			levelString(out2, level);
    			if (key != null) {
    				out2.writeBytes(key.toString());
    			} else {
    				out2.writeBytes("null");
    			}
    			out2.writeBytes(" : ");
     
    			if (value instanceof Map) {
    				debugPrintMap((Map) value, out2, nextLevel);
    			} else {
    				if (value != null) {
    					out2.writeBytes(value.toString());
    				} else {
    					out2.writeBytes("null");
    				}
    				out2.writeBytes(",\n");
    			}
    		}
    		levelString(out2, level);
    		out2.writeBytes("}\n");
    	}
     
    	protected void levelString(DataOutputStream out2, int level)
    			throws IOException {
    		if (level != 0) {
    			out2.writeBytes("\t");
    			levelString(out2, --level);
    		}
    	}
    La méthode utilisée pour le "toString" sur mes objets métiers.
    Id étant l'identifiant en base.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    @Override
    public String toString() {
    	StringBuilder sb = new StringBuilder();
    	sb.append(this.getClass().getSimpleName());
    	sb.append("@");
    	sb.append(Integer.toHexString(hashCode()));
    	sb.append("{");
    	sb.append("id : ");
    	sb.append(id);
    	sb.append("}");
    	return sb.toString();
    }


    Bon, ça fait peut-être un peu beaucoup de code, je vous l'accorde...

    Mon problème est que lors de l'écriture, j'ai un NullPointerException qui apparait dans la première méthode (writeData). L'endroit est signalé par un commentaire ici.

    Alors que dans la méthode getLastSubMap (qui construit la map de maps) je n'aie pas d'exception et je devrai si j'avais un éléments null.

    J'ai fait des impressions de map avec ma fonction de debug, et comparé les sortie et j'ai effectivement des données null (mais jamais les mêmes et jamais certaines en écrasent d'autres).

    Il est à noter que j'ai un nombre important de Mesure (~14 000 au max), mais que même en limitant ce nombre (~4 000) j'ai toujours le problème.

    Si vous avez la moindre idée, je suis très preneur !!

    PS: ci-joint les sortie text généré par debugPrintMap sur 2 essaie différents (vous pourrez voir le caractère aléatoire comme ça)
    Fichiers attachés Fichiers attachés

  2. #2
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Alors après avoir fait quelques tests, il apparait que les éléments sont bien crées (et donc non null dans la méthode getLastSubMap) mais disparaissent quelques "cycles" après sans que je sache pourquoi...

    De plus en remplaçant les TreeMap par des HashMap aucun élément ne manque; ce qui me fait dire que ce sont mes comparateurs qui sont un peu bugés... sans pour autant que je sache pourquoi.

    De plus si mes comparateurs étaient vraiment bugés pourquoi est-ce que le bug n'est pas observable avec un nombre limité de données ? Et pourquoi ils ne se trompent pas 2 fois au même endroit ?

    Bref, j'avoue que je désespère un peu... si vous avez la moindre idée je suis très preneur !

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2008
    Messages : 55
    Points : 53
    Points
    53
    Par défaut
    Bonjour, pour une fois je peux aider vu que j'ai déjà eu le même problème :

    http://www.developpez.net/forums/d74...ap-comparator/

    En gros, évite de renvoyer des égalités avec tes comparators, à moins que celles-ci proviennent de la fonction compareTo() par exemple. Sinon il faut avoir un comportement identique. Lis la doc des comparators, ça sera plus clair (perso j'avoue je n'ai pas tout lu).

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par xtope Voir le message
    [...]En gros, évite de renvoyer des égalités avec tes comparators, à moins que celles-ci proviennent de la fonction compareTo() par exemple.[...]
    Merci pour cette remarque, c'est presque ça ^^
    Sauf que moi j'ai parfois besoin d'égalité.

    En fait, pour être plus technique, je pense que pour le TreeMap les gens de chez Sun utilise un algorithme de recherche binaire (http://en.wikipedia.org/wiki/Binary_search_algorithm) qui suppose que la liste des clés soit triée et de pouvoir faire des comparaisons entre les éléments de cette liste.
    Donc l'égalité est intéressante quand tu veux que 2 objets (distinct en mémoire) représentant la même information représente la même clé dans ta map.

    Mon problème n'était pas sur le fait que je renvoyais des égalité.
    Mon problème venait du fait que je faisais ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    float o1Prof = o1.getProfondeur();
    float o2Prof = o2.getProfondeur();
    int result = 0;
    if (o1Prof < o2Prof) {
    	result = -1;
    } else if (o1Prof > o2Prof) {
    	result = 1;
    }
    Or je peux avoir dans certains cas des profondeurs qui ont pour valeur NaN (cf http://en.wikipedia.org/wiki/NaN ).
    Et mon test ne gère pas ça correctement.

    J'ai donc remplacé mon comparateur par ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    result = new Float(o1.getProfondeur()).compareTo(new Float(o2
    .getProfondeur()));
    Et là ça marche

    En tout cas merci pour l'aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 01/05/2009, 15h41
  2. Création d'objet dans des fonctions
    Par fafabzh6 dans le forum R
    Réponses: 5
    Dernier message: 22/07/2008, 14h30
  3. Disparition de valeurs dans des champs
    Par Paxaranne dans le forum Designer
    Réponses: 4
    Dernier message: 26/09/2007, 22h00
  4. encapsulation d'objets dans des sessions
    Par Steph_SOUMIER dans le forum Langage
    Réponses: 2
    Dernier message: 05/02/2007, 10h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo