2016-06-10 1 views
0

J'ai 2 ArrayList. Et je veux des éléments avec phone commun.objets communs dans 2 ArrayList

ArrayList<Contact> phone_contacts; 
ArrayList<Contact> registered_users; 

J'utilisé ci-dessous méthode pour obtenir des éléments communs:

ArrayList<Contact> common_contacts = new ArrayList<Contact>(phone_contacts); 
common_contacts.retainAll(registered_users); 

Mais, le résultat que je reçois est vide. Comment puis-je obtenir un contact téléphonique commun dans common_contacts ArrayList?

Contactez

public class Contact { 
    private String name; 
    private String phone; 

    public Contact(String name, String phone) { 
     this.name = name; 
     this.phone = phone; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getPhone() { 
     return phone; 
    } 

    public void setPhone(String phone) { 
     this.phone = phone; 
    } 
} 
+0

Vous devez surcharger les méthodes equals appropriées() et hashCode() mises en œuvre en contact classe pour faire ce travail. JVM utilise l'implémentation equals() pour comparer deux objets identiques ou non. – kosa

+0

@Nambari: Comment puis-je faire ça? Je suis nouveau en Java. –

+0

http://www.javaworld.com/article/2073330/the-contains-trap-in-java-collections.html pourrait être un bon exemple/ – kosa

Répondre

2

Tout d'abord, si vous traitez un numéro de téléphone comme identifiant, je conseille la prudence. Falsehoods Programmers Believe About Phone Numbers

Cela dit ...

retainAll utilise finalement la méthode equals. Étant donné que vous avez un objet personnalisé (et non quelque chose comme un String ou int qui ont un equals défini), la méthode la plus simple serait de définir une méthode equals pour Contact qui renvoie true si les deux ont le même numéro de téléphone.

Cependant, ce n'est peut-être pas ce que vous cherchez. Par exemple, equals devrez peut-être vérifier le nom dans d'autres contextes.

Il existe plusieurs autres approches possibles. Depuis que vous avez mentionné Android, les flux Java 8 sont actuellement désactivés. Une boucle Iterator pourrait faire le travail. Recueillir tous les numéros de téléphone pour les utilisateurs enregistrés dans un Set (de sorte que vous avez la liste unique), puis commencez par un List de tous vos contacts, et retirez ceux qui n'ont pas de numéro de téléphone de cet ensemble.

Set<String> registeredPhoneNumbers = new HashSet<>(); 
for (Contact c : registered_users) { 
    registeredPhoneNumbers.add(c.getPhone()); 
} 
List<Contact> common_contacts = new ArrayList<>(phone_contacts); 
for (Iterator<Contact> iter = common_contacts.iterator(); iter.hasNext();) { 
    Contact c = iter.next(); 
    if (!registeredPhoneNumbers.contains(c.getPhone())) { 
    iter.remove(); 
    } 
} 

Puisque vous avez mentionné dans les commentaires qu'il pourrait y avoir un million de registered_users distincts, cela pourrait être plus économe en espace:

Set<String> phoneNumbers = new HashSet<>(); 
for (Contact c : phone_contacts) { 
    phoneNumbers.add(c.getPhone()); 
} 

Set<String> overlappingNumbers = new HashSet<>(); 
for (Contact registered : registered_users) { 
    if (phoneNumbers.contains(registered.getPhone())) { 
     overlappingNumbers.add(registered.getPhone()); 
    } 
} 
List<Contact> common_contacts = new ArrayList<>(); 
for (Contact contact : phone_contacts) { 
    if (overlappingNumbers.contains(contact.getPhone())) { 
     common_contacts.add(contact); 
    } 
    } 
} 

Vous pouvez vérifier le numéro de téléphone pour null ainsi.

+0

Qu'est-ce que 'c' et' iter' dans si boucle? 'if (! registeredPhoneNumbers.contains (c.getPhone())) { iter.remove(); } ' –

+0

C'est ce que j'obtiens pour écrire une boucle Iterator quand tout ce que je fais est Java 8 ces jours-ci. Fixé. –

+0

Ça fonctionne bien. Merci! J'ai juste une question. Est-ce une méthode efficace si j'ai 1 million de 'registered_users' et des centaines de' phone_contacts'? –

0

Si vous utilisez la méthode RetainAll dans la liste la, vous obtiendrez les objets communs entre les 2 listes .. \

Exemple:

examine la liste des entiers, (juste pour l'exemple) il travaillera avec votre classe ...

public static void main(String[] args) { 
    List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5)); 
    List<Integer> list2 = new ArrayList<Integer>(Arrays.asList(1, 3, 5)); 
    List<Integer> list3 = new ArrayList<Integer>(list1); 
    list3.retainAll(list2); 
    System.out.println("List1:" + list1); 
    System.out.println("List2:" + list2); 
    System.out.println("List common:" + list3); 

    } 

Dans votre cas, les contacts de classe doit être modifiée afin d'identifier peut en quelque sorte la méthode ArrayLst.retainAll() si un contact est identique à l'autre en utilisant comme critère le numéro de téléphone ...

Modifier/améliorer le contact de classe en ajoutant la HashCode et Equals:

mais vous devez utiliser comme critères que le numéro de téléphone

public class Contact { 
    private String name; 
    private int phone; 

    public Contact(String name, int phone) { 
    this.name = name; 
    this.phone = phone; 
    } 

    public String getName() { 
    return name; 
    } 

    public void setName(String name) { 
    this.name = name; 
    } 

    @Override 
    public String toString() { 
    return "Contact [name=" + name + ", phone=" + phone + "]"; 
    } 

    @Override 
    public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    result = prime * result + phone; 
    return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
    if (this == obj) 
     return true; 
    if (obj == null) 
     return false; 
    if (getClass() != obj.getClass()) 
     return false; 
    Contact other = (Contact) obj; 
    if (phone != other.phone) 
     return false; 
    return true; 
    } 

    public int getPhone() { 
    return phone; 
    } 

    public void setPhone(int phone) { 
    this.phone = phone; 
    } 
} 

Mettre en oeuvre la liste des contacts et appeler la méthode RetainAll

public static void main(String[] args) { 
    List<Contact> list1 = new ArrayList<Contact>(Arrays.asList(new Contact(UUID.randomUUID().toString(), 1), 
     new Contact(UUID.randomUUID().toString(), 2), new Contact(UUID.randomUUID().toString(), 3), 
     new Contact(UUID.randomUUID().toString(), 4), new Contact(UUID.randomUUID().toString(), 5))); 
    List<Contact> list2 = new ArrayList<Contact>(Arrays.asList(new Contact(UUID.randomUUID().toString(), 1), 
     new Contact(UUID.randomUUID().toString(), 3), new Contact(UUID.randomUUID().toString(), 5))); 
    List<Contact> list3 = new ArrayList<Contact>(list1); 
    list3.retainAll(list2); 
    System.out.println("List1:" + list1); 
    System.out.println("List2:" + list2); 
    System.out.println("List common:" + list3); 
    } 
+0

J'ai besoin d'un téléphone commun seulement. Pas tout l'objet. Y a-t-il un moyen de modifier cela? –

+0

Tag dit Android, donc non. –