Bonjour :
Je cherche à réaliser à l'aide de Java reflect l'égalité de 2 Object Java .
Comment réaliser un equals() en profondeur sur des Collections/List ...
(et par le meme temps éviter le unchecked classe exception)
Bonjour :
Je cherche à réaliser à l'aide de Java reflect l'égalité de 2 Object Java .
Comment réaliser un equals() en profondeur sur des Collections/List ...
(et par le meme temps éviter le unchecked classe exception)
Salut,
Les Collections/List implémentent déjà la méthode equals()...
Après reste à savoir ce que tu entends par "en profondeur" !
a++
Par ailleurs, c'est quoi, ça, "unchecked class exception" ?
N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
Ce que je voudrais faire par exemple en Java reflect c'est comparer si deux object Customer sont égaux. (c'est à dire je voudrais comparer la valeur de name, des chacun des éléments de List<Item>,List<Waranty> etc ...)
Exemple :
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 class Customer(){ private String name; List<Item> items; } class Item(){ int quantite; float price; List<Waranty> waranty; } class waranty(){ String name; int duration; String price; }
Il ne faut pas passer par l'API de reflection, mais implémenter les méthodes hashCode()/equals()...
Pourquoi et comment redéfinir la méthode equals() ?
Pourquoi et comment redéfinir la méthode hashCode() ?
a++
- et tu fais ca comment pour analyser N sous List<?>
en utilisant le BeanWrapper de Spring ca pourrait marcher ?
Si les éléments de la liste implémentent correctement equals et ahshcode (voir message d'adiguba)
La reflection, oubliez, c'est bien souvent utilisé à tord et à travers par des gens qui ne veulent pas utiliser ce que les apis leur fournissent déjà.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 liste1.equals(liste2) // compare si les listes on les mêmes éléments dans le même ordre liste1.containsAll(liste2) // s'assure que tous les éléments de liste2 sont dans liste 1 liste1.containsAll(liste2) && liste2.containsAll(liste1) // les listes sont les même à l'ordre et la quantité près
Vous implémentez equals et hashcode dans votre Customer, vous pourrez alors tester leur égalité.
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 class Customer(){ private String name; List<Item> items; public boolean equals(Object o){ if (o instanceof Customer){ Customer c = (Customer) o; return c.name.equals(name) && c.items.equals(items); } return false; } public int hashCode(){ return name.hashCode() ^ items.hashCode(); } } //etc
en gros il faudrait liste tous les champs primitifs et faire un equals dessus ... c'est assez lourd si j'ai des très gros bean .
Pas un autre moyen + industrielle?
Je ne veux pas écrire dans la classe Customer.
Je souhaiterais un classe générique .
Les IDEs ont un petit menu 'generate equals and hashcode from fields' pour faire ça a ta place.
Il y a aussi lombok qui permet de générer automatiquement lors de la compilation les getters, setters, equals, hashcode et toString.
Si je suis bien, parce que t'a pas envie d'écrire deux méthodes dans "Customer", ce qui prend 30 secondes avec un IDE, tu veux un moche truc intenable qui utilise la reflection et donc va a tous les coup ajouter dans la comparaison des champs non nécessaires.... Et qui plus est sera incompatible avec les apis existantes puisque ces dernière supposent que tu implémente correctement equals et hashCode....c'est assez lourd si j'ai des très gros bean .
Pas un autre moyen + industrielle?
Je ne veux pas écrire dans la classe Customer.
Je souhaiterais un classe générique .
Tu pourrais tres bien avoir <T> la classe de ton objet
Du coup pour traiter la partie "pour tous les champs pr comparer les o1.getXXX o2.getXX" on pourrait utiliser Java reflect ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 class CompareProcessor implements Comparator<T>(){ compare(T o1, T o2) { //pour tous les champs pr comparer les o1.getXXX o2.getXX //pour toutes les listes objet comparer si tous les elements sont bien la .:ccool: } }
Va pendre l'architecte / analyste qui t'as dit ça.
Sinon tu as commons lang avec son EqualsBuilder.reflectionEquals() qui fait ton boulot, mais en général ca se casse les dents parce que t'as justement des champs privés dans le data que t'as pas vu et qui ne doivent pas jouer dans l'égalité, mais la reflection les utilise. Et le jour où les beans data changeront un tout petit peu, la reflection va t'exploser à la figure.
Tas la problematique ..." progiciels" ;-) d'ou tas pas la main dessus ..
J'ai deja essayer EqualsBuilder.reflectionEquals() ca ne passe pas à cause des champs private...
Voila mon code en utilisant Java reflect pour les champs primitifs.
Manque la reflections ...Pour les types Complexes type Liste et Collections
comment faire ?
Est ce que un containsAll suffirait ?
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 public static <T, Y> Boolean EgalityFields(T from, Y too) { Field[] fromFields = from.getClass().getDeclaredFields(); Field[] tooFields = too.getClass().getDeclaredFields(); //permet acceder aux champs private . AccessibleObject.setAccessible(fromFields, true); AccessibleObject.setAccessible(tooFields, true); if (fromFields != null && tooFields != null) { for(Field f : too.getClass().getDeclaredFields()){ try { f.setAccessible(true); Object temp2 = f.get(too); for (Field fromTemp : fromFields) { debug = fromTemp.getName(); fromTemp.setAccessible(true); //Name variable match if(fromTemp.getName().equals(f.getName()) && fromTemp.getClass().isAssignableFrom(f.getClass())){ Type t = fromTemp.getGenericType(); System.out.println("==> Type Pojo :"+fromTemp.getGenericType()+" Declaring Type : "+fromTemp.getDeclaringClass()+" Type : "+fromTemp.getType()); //Gere les types primitifs . if(!fromTemp.get(from).equals(f.get(too))){ return false ; } } } } catch (Exception e) { e.printStackTrace(); } }//end of loop } }
Et pourtant, d'après la javadoc:
public static boolean reflectionEquals(Object lhs,
Object rhs)
This method uses reflection to determine if the two Objects are equal.
It uses AccessibleObject.setAccessible to gain access to private fields.containsAll, equals, etc. Tout ce ne marchera pas correctement si les éléments à l'intérieur n'implémentent pas correctement equals/hashcode. Vous pouvez parcourir les liste à la main et comparer les champs.Est ce que un containsAll suffirait ?
PS: cette déclaration me semble incorrect:
Si les objets n'ont pas un type commun, ca n'a pas de sens de les comparer:
Code : Sélectionner tout - Visualiser dans une fenêtre à part public static <T, Y> Boolean EgalityFields(T from, Y too)
Un customer n'est pas un item.
Code : Sélectionner tout - Visualiser dans une fenêtre à part public static <T> Boolean EgalityFields(T from, T too)
Enfin, tout l'idée de l'api reflection est, a mon avis, mal partie. Si vous n'avez pas accès aux objet, utilisez les getters/setters des objets pour déterminer si ils sont égaux. C'est bien plus propre, ne nécessite pas de bidouille du securitymanager et risque mois de vous exploser à la figure.
je verrais plutot ce genre de code, plus propre. Et bien plus rapide à coder que la prise de tete reflection
Avec au moins l'avantage qu'on vois tout de suite quels sont vos critères.
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 // pour les types de base comme String, Integer, etc public static boolean equals(Object a, Object b){ if ((a==null) && (b==null)) return true; if (a==null ||b == null) return false; return a.equals(b); } // Testeur de collection, ne supporte pas les boucle du style customer -> items -> vendor -> customers public static <T> boolean equalsCollection(Collection<T> a, Collection<T> b, EqualTester<T> equalTester) { if (a==null && b==null) return true; if (a==null ||b ==null) return false; if (a.size()!=b.size()) return false; Iterator<T> ta = a.iterator(); Iterator<T> tb = b.iterator(); while (ta.hasNext()) if (!equalTester.isEquals(ta.next(),tb.next())) return false; return true; } // teste deux customers public static boolean equals(Customer a, Customer b){ return equals(a.getName(),b.getName()) && equals(a.getLastname(),b.getLastname()) && equals(a.getPhone(),b.getPhone())&& equals(a.getAddresse(),b.getAddresse()) && equals(a.getItems(),b.getItems(),Item.class, new EqualTester<Item>(){ public boolean isEquals(Item a,Item b) {return equals(a,b);} }) ; } public static boolean equals(Adresse a, Adresse b){ //todo } public static boolean equals(Item a, Item b){ //todo } }
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager