2017-07-11 3 views
3

J'utilise des objets java comme ceci:Retirez certains éléments répétés dans une liste

public class GeoName { 
    private String country; 
    private String city; 
    private float lat; 
    private float lon; 
} 

Je reçois une liste de toponyme et je voudrais supprimer les villes en double dans le même pays qui sont dans la liste , aussi efficace que possible. Je veux dire, si je reçois la liste suivante:

Madrid, Spain, ... 
London, England, ... 
Madrid, Mexico, ... 
London, England, ... 
Paris, France, ... 
Madrid, Spain, ... 

Je voudrais supprimer les éléments répétés (ville + pays) jusqu'à ce que la liste était comme ça:

Madrid, Spain, ... 
London, England, ... 
Madrid, Mexico, ... 
Paris, France, ... 

Je travaille là-dessus mais je ne sais pas comment le faire!

Une idée, s'il vous plaît?

Merci! PS: Je ne peux pas utiliser une collection Set car j'ai trouvé le nom d'une ville répété dans un pays avec une latitude et une longitude différentes (c'est étrange, mais elles existent). Il ne s'agirait donc pas d'un élément d'égalité parfaite sur l'ensemble

+0

Salut, Qu'avez-vous essayé jusqu'ici? –

+1

Utilisez un 'Set' au lieu d'un tableau. – victor

+0

J'ai répondu à une question comme celle-ci hier et elle a été supprimée T_T – Daedric

Répondre

1

Vous pouvez implémenter hashCode() et equals() pour GeoName qui ne considère que le pays et la ville.

@Override 
public boolean equals(Object o) { 
    if (this == o) 
     return true; 
    if (o == null || getClass() != o.getClass()) 
     return false; 

    GeoName geoName = (GeoName) o; 

    if (!country.equals(geoName.country)) 
     return false; 
    return city.equals(geoName.city); 
} 

@Override 
public int hashCode() { 
    int result = country.hashCode(); 
    result = 31 * result + city.hashCode(); 
    return result; 
} 

Après cela, vous pouvez utiliser un HashSet() pour mettre tous GeoNames en. Doublons est réglé automatiquement et efficacement.

List<GeoName> myInputList = ...; 
    Set<GeoName> geoSet = new HashSet<>(myInputList); 
1

Cela devrait le faire:

Je crée votre classe avec une méthode equals modifiée puis vérifier si 2 cas de test de cette classe sont les mêmes en utilisant ladite méthode equals.

class GeoName { 
    private String country; 
    private String city; 

    public GeoName(String country, String city) { 
     this.country = country; 
     this.city = city; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } 
     if (getClass() != obj.getClass()) { 
      return false; 
     } 
     final GeoName other = (GeoName) obj; 
     if (!Objects.equals(this.country, other.country)) { 
      return false; 
     } 
     if (!Objects.equals(this.city, other.city)) { 
      return false; 
     } 
     return true; 
    } 
} 

classe Test:

public class Cities { 
    public static void main(String[] args) { 
      // ArrayList<GeoName> geos = new ArrayList<>(); 

      GeoName test = new GeoName("Madrid", "Spain"); 
      GeoName test1 = new GeoName("Madrid", "Mexico"); 

      if (test.equals(test)) { 
       System.out.println("True 1"); 
      } 

      if (test.equals(test1)) { 
       System.out.println("True 2"); 
      } 
    } 
} 

Sortie:

True 1 

Vous serez alors en boucle le tableau et vérifiez tous et si elle ne marche pas existe, vous l'ajouter au tableau Je vous laisse ça.

+0

Vous ne devriez pas le faire comme ça. Vous auriez à comparer chaque instance avec une autre avec des équations, ce qui donnerait une complexité 'O (n^2)'. Utiliser HashSet est plus général, plus propre et s'exécute dans 'O (n)'. – A1m

+0

Eh bien, c'est bien pour les petites échelles. – Daedric

1

Ceci est un exemple complet:

import java.util.HashSet; 
import java.util.Objects; 
import java.util.Set; 

public class GeoName { 
    private String country, city; 
    private float lat, lon; 

    public GeoName(String country, String city, float lat, float lon){ 
     this.country = country; 
     this.city = city; 
     this.lat = lat; 
     this.lon = lon; 
    } 

    @Override 
    public boolean equals(Object other){ 
     if(other==null) return false; 
     if(other instanceof GeoName){ 
     return ((GeoName)other).city.equals(this.city) && 
       ((GeoName)other).country.equals(this.country); 
     } 
     return false; 
    } 

    @Override 
    public String toString(){ 
     return city + ", "+ country + 
       ", " + lat +", " + lon; 
    } 


    @Override 
    public int hashCode(){ 
     return Objects.hash(country, city); 

    } 

    // to test 
    public static void main(String[] args) { 
     List<GeoName> list = new ArrayList<>(); 

     list.add(new GeoName("Madrid", "Spain",1.0f, 2.0f)); 
     list.add(new GeoName("England", "London",3.0f, 4.0f)); 
     list.add(new GeoName("England", "London",3.0f, 4.0f)); 
     list.add(new GeoName("France", "Paris",7.0f, 9.0f)); 
     list.add(new GeoName("Mexico", "Madrid",9.0f, 10.0f)); 

     Set<GeoName> set = new HashSet<>(list); 

     for(GeoName geoName : set){ 
      System.out.println(geoName); 
     }   
    }  
} 

Sortie:

London, England, 3.0, 4.0 
Madrid, Mexico, 9.0, 10.0 
Paris, France, 7.0, 9.0 
Spain, Madrid, 1.0, 2.0 
2

Pour enlever l'entrée en double de la collecte de données personnalisées (par exemple toponyme) mettre en œuvre les equals() et hashCode() méthodes

Puis ajoutez les données dans un ensemble pour supprimer l'entrée en double.

Implémentez les méthodes equals() et hashcode() en fonction de votre logique pour identifier les données dupliquées.