So finden Sie ein Objekt in einer ArrayList nach Eigenschaft

78

Wie kann ich ein Objekt finden Carnet, in einem zu ArrayList<Carnet>wissen , seine Eigenschaft codeIsin.

List<Carnet> listCarnet = carnetEJB.findAll();

public class Carnet {

    private String codeTitre;
    private String nomTitre;
    private String codeIsin;

    // Setters and getters

}
user861594
quelle
3
mit indexOf(), vorausgesetzt, Ihr Objekt überschreibt equals().
Lordo
Die Klasse Carnet befindet sich in der JAR-Datei. Ich kann equals () nicht überschreiben.
1
Wenn ich Sie wäre, würde ich den Quellcode von wo auch immer finden und ihn gleich und hashCode implementieren lassen. Die einzige andere Alternative besteht darin, die Sammlung manuell zu durchlaufen und die Gleichheit der Mitglieder zu überprüfen.
Thihara
Ich würde lieber eine Karte anstelle einer Liste verwenden. Wenn Sie häufig nach Objekten suchen und die Leistung ein Problem darstellt, ist eine sortierte Karte möglicherweise besser. Die Implementierung und Verwendung von Equal für diesen Zweck ist aus meiner Sicht hässlich.
mmirwaldt
2
Für Java 8 können Sie den Stream aus der ArrayList abrufen und einen Filter (e-> e.codeIsIn.equals (...)) darauf anwenden.
Thorbjørn Ravn Andersen

Antworten:

77

Sie können nicht ohne eine Iteration.

Option 1

Carnet findCarnet(String codeIsIn) {
    for(Carnet carnet : listCarnet) {
        if(carnet.getCodeIsIn().equals(codeIsIn)) {
            return carnet;
        }
    }
    return null;
}

Option 2

Überschreiben Sie die equals()Methode von Carnet.

Option 3

Speichern Sie Ihre Listals Mapstattdessen mit codeIsInals Schlüssel:

HashMap<String, Carnet> carnets = new HashMap<>();
// setting map
Carnet carnet = carnets.get(codeIsIn);
Menno
quelle
8
Ich bekomme Option2 nicht. Ich überschreibe equals()und mache dann was?
idclev 463035818
@ idclev463035818 Ich vermute, verwenden Sie die ArrayList.indexOfMethode
Moosefeather
71

In Java8 können Sie Streams verwenden:

public static Carnet findByCodeIsIn(Collection<Carnet> listCarnet, String codeIsIn) {
    return listCarnet.stream().filter(carnet -> codeIsIn.equals(carnet.getCodeIsin())).findFirst().orElse(null);
}

Wenn Sie viele verschiedene Objekte haben (nicht nur Carnet) oder diese anhand verschiedener Eigenschaften (nicht nur nach cideIsin) suchen möchten , können Sie eine Dienstprogrammklasse erstellen, um diese Logik darin zu kapseln:

public final class FindUtils {
    public static <T> T findByProperty(Collection<T> col, Predicate<T> filter) {
        return col.stream().filter(filter).findFirst().orElse(null);
    }
}

public final class CarnetUtils {
    public static Carnet findByCodeTitre(Collection<Carnet> listCarnet, String codeTitre) {
        return FindUtils.findByProperty(listCarnet, carnet -> codeTitre.equals(carnet.getCodeTitre()));
    }

    public static Carnet findByNomTitre(Collection<Carnet> listCarnet, String nomTitre) {
        return FindUtils.findByProperty(listCarnet, carnet -> nomTitre.equals(carnet.getNomTitre()));
    }

    public static Carnet findByCodeIsIn(Collection<Carnet> listCarnet, String codeIsin) {
        return FindUtils.findByProperty(listCarnet, carnet -> codeIsin.equals(carnet.getCodeIsin()));
    }
}
oleg.cherednik
quelle
2

Hier ist eine Lösung mit Guava

private User findUserByName(List<User> userList, final String name) {
    Optional<User> userOptional =
            FluentIterable.from(userList).firstMatch(new Predicate<User>() {
                @Override
                public boolean apply(@Nullable User input) {
                    return input.getName().equals(name);
                }
            });
    return userOptional.isPresent() ? userOptional.get() : null; // return user if found otherwise return null if user name don't exist in user list
}
Phan Van Linh
quelle
2

Hier ist eine andere Lösung, die Guava in Java 8 verwendet und das übereinstimmende Element zurückgibt, falls eines in der Liste vorhanden ist. Wenn mehr als ein Element übereinstimmt, löst der Kollektor eine IllegalArgumentException aus. Eine Null wird zurückgegeben, wenn keine Übereinstimmung vorliegt.

Carnet carnet = listCarnet.stream()
                    .filter(c -> c.getCodeIsin().equals(wantedCodeIsin))
                    .collect(MoreCollectors.toOptional())
                    .orElse(null);
savac
quelle
1

Wenn Sie Java 8 verwenden und Ihre Suche möglicherweise null zurückgibt, können Sie versuchen, die optionale Klasse zu verwenden.

So finden Sie ein Carnet:

private final Optional<Carnet> findCarnet(Collection<Carnet> yourList, String codeIsin){
    // This stream will simply return any carnet that matches the filter. It will be wrapped in a Optional object.
    // If no carnets are matched, an "Optional.empty" item will be returned
    return yourList.stream().filter(c -> c.getCodeIsin().equals(codeIsin)).findAny();
}

Nun eine Verwendung dafür:

public void yourMethod(String codeIsin){
    List<Carnet> listCarnet = carnetEJB.findAll();

    Optional<Carnet> carnetFound = findCarnet(listCarnet, codeIsin);

    if(carnetFound.isPresent()){
        // You use this ".get()" method to actually get your carnet from the Optional object
        doSomething(carnetFound.get());
    }
    else{
        doSomethingElse();
    }
}
RKrum
quelle
0

Wenn Sie mit der Antwort von Oleg ALLE Objekte in einer Liste finden möchten, die nach einer Eigenschaft gefiltert ist, können Sie Folgendes tun:

//Search into a generic list ALL items with a generic property
public final class SearchTools {
       public static <T> List<T> findByProperty(Collection<T> col, Predicate<T> filter) {
           List<T> filteredList = (List<T>) col.stream().filter(filter).collect(Collectors.toList());
           return filteredList;
     }

//Search in the list "listItems" ALL items of type "Item" with the specific property "iD_item=itemID"
public static final class ItemTools {
         public static List<Item> findByItemID(Collection<Item> listItems, String itemID) {
             return SearchTools.findByProperty(listItems, item -> itemID.equals(item.getiD_Item()));
         }
     }
}

und ähnlich, wenn Sie ALLE Elemente in einer HashMap mit einer bestimmten Eigenschaft filtern möchten

//Search into a MAP ALL items with a given property
public final class SearchTools {
       public static <T> HashMap<String,T> filterByProperty(HashMap<String,T> completeMap, Predicate<? super Map.Entry<String,T>> filter) {
           HashMap<String,T> filteredList = (HashMap<String,T>) completeMap.entrySet().stream()
                                .filter(filter)
                                .collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue()));
           return filteredList;
     }

     //Search into the MAP ALL items with specific properties
public static final class ItemTools {

        public static HashMap<String,Item> filterByParentID(HashMap<String,Item> mapItems, String parentID) {
            return SearchTools.filterByProperty(mapItems, mapItem -> parentID.equals(mapItem.getValue().getiD_Parent()));
        }

        public static HashMap<String,Item> filterBySciName(HashMap<String,Item> mapItems, String sciName) {
            return SearchTools.filterByProperty(mapItems, mapItem -> sciName.equals(mapItem.getValue().getSciName()));
        }
    }
user1084363
quelle