Aller au contenu

[Résolu][Java] Utiliser la généricité


windu.2b

Messages recommandés

Bonjour,

J'aimerais faire une classe héritant d'ArrayList pour y stocker des valeurs de type int, float, double... afin de pouvoir faire des sum(), average(), très facilement.

Je veux donc me baser sur la généricité de Java 5, afin de ne pas tenir compte du type exact (Integer, Float, Double...) mais j'ai des problèmes!

Voilà ce que j'ai déjà fait:

/**
* MathList.java 5 sept. 07 windu.2b
*/
import java.util.*;

/**
* @author windu.2b
* 
*/
public class MathList<Number> extends ArrayList
{
/**
 * 
 */
private static final long	serialVersionUID	= 6905001321588101837L;




@SuppressWarnings("unchecked")
public MathList( String s )
{
	StringTokenizer st = new StringTokenizer( s );
	while ( st.hasMoreTokens() )
	{
		add( ( Number ) st.nextToken() );
	}
}



public Number sum()
{
	Number sum;
	for( Object o : toArray() )
	{
		// que faire?
	}

	return sum;
}
}

Le constructeur est prévu pour pouvoir recevoir une chaîne de valeurs séparées par des ';' (c'est spécifique à mon utilisation). Là où cela coince, c'est dans la boucle for: je ne sais pas comment ajouter les valeurs :francais:

Si quelqu'un a une idée, ou une autre solution à me proposer :iloveyou:

Lien vers le commentaire
Partager sur d’autres sites

Deux problèmes dans ta classe :

1. Caster sauvagement une String (renvoyée par st.nextToken()) en Number me paraît pour le moins dangereux

2. C'est bien beau d'avoir un ensemble de Numbers, mais on ne peut effectuer aucune opération dessus. Il faudrait d'abord les transformer en int, double... (avec intValue(), doubleValue, etc.), mais comme tu ne connais pas d'avance ton type...

Il faudrait que tu reformules ton besoin en termes fonctionnels, et on verra si on peut trouver une solution technique acceptable.

Lien vers le commentaire
Partager sur d’autres sites

Merci pour vos réponses!

Tout débord oui le cast est sans doute un peu bourrin, je reverrai ça...

Ensuite, non je ne peux pas changer de langages.

Ensuite, je ne suis pas sûr d'avoir bien compris ce passage:

Il faudrait que tu reformules ton besoin en termes fonctionnels, et on verra si on peut trouver une solution technique acceptable.
Lien vers le commentaire
Partager sur d’autres sites

Hé bien, plutôt que de nous dire : je veux absolument utiliser une ArrayList générique qui prend une String en param, dis-nous plutôt quel est ton besoin exact en termes fonctionnels (ex: effectuer des opérations sur un ensemble de valeurs de type entier). Si ça se trouve, la solution optimale n'utilise pas du tout les génériques, voire même pas les collections...

Lien vers le commentaire
Partager sur d’autres sites

Ah oki... désolé

Donc je dois récupérer des données contenues dans une BDD, et certaines de ces données sont stockées ainsi:

1;2;3;4:5;6;7;8;9;10

Sauf que parfois ce sont des float et non des entiers (je sais quelles cases de la table contiennent des int et lesquelles contiennent des float, donc le pb n'est pas trop à ce niveau là).

Ce que je compte faire, c'est récupérer cette valeur, la "casser" pour en extraire les valeurs, et stocker le tout sous une *List ou une Collection.

Je comptais ensuite créer une classe héritant de *List (ou Collection) afin de faciliter tout ça, et surtout me permettre les calculs dont j'ai besoin (sommes et moyennes principalement) sur toutes ces valeurs.

Lien vers le commentaire
Partager sur d’autres sites

Hummm je t'ai bricolé ça, dis-moi si ça te convient ?

import java.util.ArrayList;
import java.util.Iterator;

public class GenericMathList<E extends Number> extends ArrayList<Number>
{
private static final long serialVersionUID = -7103399393697283325L;

//	======================================================================
//	Parseurs de listes de valeurs 
//	======================================================================

public void parseInts(String intList)
{
	String[] ints = intList.split(";");
	for(String s:ints)
	{	add(new Integer(s));			
	}
}

public void parseFloats(String floatList)
{
	String[] ints = floatList.split(";");
	for(String s:ints)
	{	add(new Float(s));			
	}
}

//	======================================================================
//	Méthodes mathématiques
//	======================================================================

public int intSum()
{
	int sum = 0;
	for(Iterator<Number> it=iterator(); it.hasNext()
	{	sum += it.next().intValue();
	}
	return sum;		
}

public float floatSum()
{
	float sum = 0.0F;
	for(Iterator<Number> it=iterator(); it.hasNext()
	{	sum += it.next().floatValue();
	}
	return sum;		
}

public float intAvg()
{
	return intSum()/size();
}

public float floatAvg()
{
	return floatSum()/size();
}

//	======================================================================
//	Exemple d'utilisation
//	======================================================================

public static void main(String[] args)
{
	// Opérations sur les floats
	String floats = "1.1;2.1;3.1;4.1";
	GenericMathList<Float> gmlf = new GenericMathList<Float>();
	gmlf.parseFloats(floats);
	System.out.printf("%25s %-6d%n", 	"Int sum of float list :", gmlf.intSum());
	System.out.printf("%25s %-6.2f%n", 	"Float sum of float list :", gmlf.floatSum());

	// Opérations sur les Ints
	String ints = "1;8;2;4;6";
	GenericMathList<Integer> gmli = new GenericMathList<Integer>();
	gmli.parseFloats(ints);
	System.out.printf("%25s %-6d%n", 	"Int sum of int list :", gmli.intSum());
	System.out.printf("%25s %-6.2f%n", 	"Float sum of int list :", gmli.floatSum());
}


}

Lien vers le commentaire
Partager sur d’autres sites

Pour les fonctions sum tu peux tjs faire des fonctions static...

import java.util.*;

public class MathList<T extends Number> extends Vector<Number>
{
/**
 *
 */
private static final long	serialVersionUID	=
6905001321588101837L;

public MathList(String s, Class c)
{
	if (c == Integer.class)
		parseInts(s);
	if (c == Float.class)
		parseFloats(s);
}

public void parseInts(String intList)
{
	String[] ints = intList.split(";");
	for(String s:ints)
		{ add(new Integer(s));
		}
}

public void parseFloats(String floatList)
{
	String[] ints = floatList.split(";");
	for(String s:ints)
		{ add(new Float(s));
		}
}

static public Integer sum(MathList<Integer> l) {
	int res = 0;
	for (Object e : l)
		res += ((Integer)e).intValue();

	return new Integer(res);
}

static public Float sum(MathList<Float> l) {
	float res = 0.0f;
	for (Object e : l)
		res += ((Float)e).floatValue();

	return new Float(res);
}

static public void main(String args[]) {
	MathList<Integer> l1 = new MathList<Integer>("1;2;3", Integer.class);
	MathList<Float> l2 = new MathList<Float>("1.5;2.;3.3", Float.class);

	System.out.println("sum 1 : " + MathList.sum(l1));
	System.out.println("sum 2 : " + MathList.sum(l2));
}
}

Lien vers le commentaire
Partager sur d’autres sites

Hummm, je ne vois pas bien l'intérêt des modifications apportées par PiFou86 ?

- Pourquoi hériter de Vector qui est inutilement synchronisé ?

- Pourquoi utiliser des méthodes statiques puisque de toute façon on est obligé d'instancier une MathList ?

- En déclarant un constructeur à arguments et en forçant son utilisation, le programmeur ne peut plus utiliser les autres constructeurs d'ArrayList

- Ses méthodes sum() forcent l'utilisation de MathList<Float> ou <Integer>. Et si l'utilisateur avait déjà placé d'autres Numbers (Double, par exemple) dans la liste et voulait effectuer des calculs avec ?

Lien vers le commentaire
Partager sur d’autres sites

Enfin si tu veux vraiment considérer la classe comme une classe utilitaire externe à ta liste, tu peux faire comme ça :

import java.util.ArrayList;
import java.util.List;

public class MathListUtils
{


//	======================================================================
//	Parseurs de listes de valeurs 
//	======================================================================

// Note : utilisable avec List<Number> et <Integer>
public static void addInts(List<? super Integer> list, String intList)
{
	String[] ints = intList.split(";");
	for(String s:ints)
	{	list.add(new Integer(s));			
	}
}

// Note : utilisable avec List<Number> et <Float>
public static void addFloats(List<? super Float> list, String floatList)
{
	String[] floats = floatList.split(";");
	for(String s:floats)
	{	list.add(new Float(s));			
	}
}

//	======================================================================
//	Méthodes mathématiques
//	======================================================================


// Note : utilisable avec List<Number> et et <Integer> et <Float>
public static int intSum(List<? extends Number> list)
{
	int sum = 0;
	for(Number n:list)
	{	sum += n.intValue();
	}
	return sum;		
}

// Note : utilisable avec List<Number> et et <Integer> et <Float>
public static float floatSum(List<? extends Number> list)
{
	float sum = 0.0F;
	for(Number n:list)
	{	sum += n.floatValue();
	}
	return sum;		
}

// Note : utilisable avec List<Number> et et <Integer> et <Float>
public float intAvg(List<? extends Number> list)
{
	return MathListUtils.intSum(list)/list.size();
}

// Note : utilisable avec List<Number> et et <Integer> et <Float>
public float floatAvg(List<? extends Number> list)
{
	return MathListUtils.floatSum(list)/list.size();
}

//	======================================================================
//	Exemple d'utilisation
//	======================================================================

public static void main(String[] args)
{
	// Opérations sur les floats
	List<Number> floatNumbers = new ArrayList<Number>();
	MathListUtils.addFloats(floatNumbers, "1.1;2.1;3.1;4.1");
	System.out.printf("%25s %-6d%n", 	"Int sum of float list :", 		MathListUtils.intSum(floatNumbers));
	System.out.printf("%25s %-6.2f%n", 	"Float sum of float list :", 	MathListUtils.floatSum(floatNumbers));	

	// Opérations sur les floats
	List<Number> intNumbers = new ArrayList<Number>();
	MathListUtils.addInts(intNumbers, "1;2;10;4;8");
	System.out.printf("%25s %-6d%n", 	"Int sum of float list :", 		MathListUtils.intSum(intNumbers));
	System.out.printf("%25s %-6.2f%n", 	"Float sum of float list :", 	MathListUtils.floatSum(intNumbers));	
}


}

Lien vers le commentaire
Partager sur d’autres sites

Le paramètre dans le constructeur c'est simplement pour connaitre le type dans le constructeur.

Le problème de faire des intSum et floatSum, c'est que tu dois faire des floatSum ou intSum... ce qui peut être chiant si tu veux être générique. Donc comme tu dis dans ton exemple, si le programmeur veut permettre d'autres types, il suffit d'écrire les autres méthodes, c'est rapide et homogène. Après c'est une question de gout.

Pour le vector ou l'arraylist, il n'y a pas de rapport, je voulais seulement un container :)

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...