web-dev-qa-db-fra.com

Comment archiver Java si Set contient un objet avec une valeur de chaîne?

J'ai un ensemble d'objets. Chaque objet a une valeur de chaîne.

Je dois sélectionner tous les objets dont la valeur this est égale à "direction".

Est-ce possible sans itérer sur l'ensemble?

Merci.

19
user710818

En général, non. Vous devez parcourir l'ensembles et vérifier chaque objet pour voir si la propriété est égale à la valeur que vous recherchez. Il s'agit d'une opération O(n).

Il y a une situation dans laquelle vous pouvez le faire sans itérer. Si la méthode equals de votre objet est définie en termes d'égalité de cette propriété String, et si la méthode hashCode est également implémentée correctement, vous pouvez utiliser la fonction hashSet.contains pour trouver un objet avec la valeur correcte dans O(1) temps sans nécessiter d'itération sur l'ensemble.

Comme je l'ai mentionné, il s'agit d'un cas d'utilisation très spécifique et non d'une solution générale. Cela pourrait être utile si la chaîne était une sorte d'identifiant unique, mais cela ne fonctionnera pas pour votre cas d'utilisation spécifique.

Vous pouvez également envisager d'autres collections qui seraient mieux adaptées à votre cas d'utilisation. Vous pouvez par exemple, si vous utilisez Guava, vous pouvez alors envisager d'utiliser un Multimap .

Connexes

24
Mark Byers

Oui, cela est possible en écrasant la méthode equals().

@Override 
public boolean  equals (Object object) {

}

Vous voulez juste vérifier que tout fonctionne dans la méthode des égaux.

Code:

package com.webapp.test;

import Java.util.ArrayList;
import Java.util.List;

public class EmployeeModel {    

    public EmployeeModel(String name, String designation, long age) {
        this.name = name;
        this.designation = designation;
        this.age = age;
    }

    private String name;
    private String designation;
    private long age;

    public String getName() {
        return name;
    }

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

    public String getDesignation() {
        return designation;
    }

    public void setDesignation(String designation) {
        this.designation = designation;
    }

    public long getAge() {
        return age;
    }

    public void setAge(long age) {
        this.age = age;
    }

    @Override
    public boolean equals (Object object) {
        boolean result = false;
        if (object == null || object.getClass() != getClass()) {
            result = false;
        } else {
            EmployeeModel employee = (EmployeeModel) object;
            if (this.name == employee.getName() && this.designation == employee.getDesignation() && this.age.equals(employee.getAge())) {
                result = true;
            }
        }
        return result;
    }
}

public static void main(String args[]) {
    EmployeeModel first = new EmployeeModel("Sameer", "Developer", 25);
    EmployeeModel second = new EmployeeModel("Jon", "Manager", 30);
    EmployeeModel third = new EmployeeModel("Priyanka", "Tester", 24);

    List<EmployeeModel> employeeList = new ArrayList<EmployeeModel>();
    employeeList.add(first);
    employeeList.add(second);
    employeeList.add(third);

    EmployeeModel checkUserOne = new EmployeeModel("Sameer", "Developer", 25);
    System.out.println("Check checkUserOne is in list or not ");
    System.out.println("Is checkUserOne Present = ? " + employeeList.contains(checkUserOne));

    EmployeeModel checkUserTwo = new EmployeeModel("Tim", "Tester", 24);
    System.out.println("Check checkUserTwo is in list or not");
    System.out.println("Is checkUserTwo Present = ? " + employeeList.contains(checkUserTwo));

}

Sortie:

Check checkUserOne is in list or not 
Is checkUserOne Present = ? true
Check checkUserTwo is in list or not 
Is checkUserTwo Present = ? false
8
Sameer Kazi

Vous pouvez également utiliser Predicate comme dans cette question pour filtrer la liste: Quelle est la meilleure façon de filtrer une collection Java?

3
Michael Laffargue

Je sais que c'est une vieille question, mais ...

Réponse courte: NON, ce n'est pas possible ...

L'utilisation de equals() ou contains() comme recommandé par d'autres boursiers doit être limitée aux situations où les attributs que vous utilisez pour le filtrage font en réalité partie de l'identité des objets. Je ne vois aucun moyen mais un algorithme O(n).

Si vous envisagez des fonctions natives, Java 8 a apporté Stream API et les concepts de Functional Programming, permettant des appels de boucle plus faciles et plus propres. Néanmoins il convient de noter que pour votre situation, tous les objets de votre collection devront être vérifiés, de sorte que la complexité restera O (n).

Exemple avec Java 8's stream().filter()

public static void main(String[] args...){
    Set<MyClass> mySet = new HashSet<>();
    mySet.add(new MyClass("Obj 1", "Rio de Janeiro"));
    mySet.add(new MyClass("Obj 2", "London"));
    mySet.add(new MyClass("Obj 3", "New York"));
    mySet.add(new MyClass("Obj 4", "Rio de Janeiro"));

    Set<MyClass> filtered = mySet.stream()
                                 .filter(mc -> mc.getCity().equals('Rio de Janeiro'))
                                 .collect(Collectors.toSet());

    filtered.forEach(mc -> System.out.println("Object: "+mc.getName()));

    // Result:
    //    Object: Obj 1 
    //    Object: Obj 4 
}
2
Felipe Leão

Vous pouvez toujours utiliser la méthode contains() également.

Il vous suffit de mapper votre ensemble initial et de le transformer en ensemble de chaînes avec uniquement les valeurs de champ que vous souhaitez vérifier si elles existent dans l'ensemble de votre objet.

Voir l'exemple suivant basé sur les réponses précédentes de Felipe Leão et Michael Laffargue .

public static void main(String[] args...){
     Set<MyClass> mySet = new HashSet<>();
     mySet.add(new MyClass("Obj 1"));
     mySet.add(new MyClass("Obj 2"));
     mySet.add(new MyClass("Obj 3"));

     Set<String> mapped = mySet.stream()
                             .map(MyClass::getField())
                             .collect(Collectors.toSet());

     mapped.contains("Obj 1");
     mapped.contains("Obj 2");
     mapped.contains("Obj 4");

     // Result:
     //     true 
     //     true
     //     false

}

0
Nazar Poshtarenko