java #arraylist
#java #arraylist #Коллекции
Вопрос:
Как я могу найти объект, Carnet
, ArrayList<Carnet>
зная его свойство codeIsin
.
List<Carnet> listCarnet = carnetEJB.findAll();
public class Carnet {
private String codeTitre;
private String nomTitre;
private String codeIsin;
// Setters and getters
}
Комментарии:
1. с
indexOf()
помощью, при условии, что ваш объект переопределяетсяequals()
.2. класс Carnet находится внутри файла jar, я не могу переопределить equals()
3. На вашем месте я бы нашел исходный код откуда угодно и реализовал его equals и hashCode. Единственная другая альтернатива — вручную перебирать коллекцию и проверять равенство членов.
4. Я бы предпочел использовать карту вместо списка. Если вы часто ищете объекты и производительность является проблемой, отсортированная карта может быть лучше. Реализация и использование equal для этой цели, с моей точки зрения, уродливы.
5. Для Java 8 вы можете получить поток из ArrayList и применить к нему filter(e-> e.codeIsIn.equals(…)) .
Ответ №1:
В Java8 вы можете использовать потоки:
public static Carnet findByCodeIsIn(Collection<Carnet> listCarnet, String codeIsIn) {
return listCarnet.stream().filter(carnet -> codeIsIn.equals(carnet.getCodeIsin())).findFirst().orElse(null);
}
Кроме того, если у вас много разных объектов (не только Carnet
) или вы хотите найти его по разным свойствам (не только по cideIsin
), вы можете создать служебный класс, чтобы экапсулировать в него эту логику:
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()));
}
}
Ответ №2:
Вы не можете без итерации.
Вариант 1
Carnet findCarnet(String codeIsIn) {
for(Carnet carnet : listCarnet) {
if(carnet.getCodeIsIn().equals(codeIsIn)) {
return carnet;
}
}
return null;
}
Вариант 2
Переопределите equals()
метод Carnet
.
Вариант 3
Вместо этого сохраняем ваш List
как a Map
, используя codeIsIn
в качестве ключа:
HashMap<String, Carnet> carnets = new HashMap<>();
// setting map
Carnet carnet = carnets.get(codeIsIn);
Комментарии:
1. Я не получаю Option2. Я переопределяю
equals()
, а затем делаю что?2. @idclev463035818 Я предполагаю использовать
ArrayList.indexOf
метод3. Вы можете переопределить метод equals(), который гарантирует, что когда ТОЛЬКО это конкретное поле (в данном случае codeIsin) одного объекта равно тому же полю в другом объекте, которое они считают равным. Затем вы можете создать объект с этим полем и тем же значением (таким же, как в объекте, который вы ищете) и выполнить поиск по списку следующим образом: listCarnet.get(listCarnet.indexOf(ОБЪЕКТ, КОТОРЫЙ ВЫ ТОЛЬКО ЧТО СОЗДАЛИ)).
Ответ №3:
Если вы используете Java 8 и если возможно, что ваш поиск возвращает null, вы можете попробовать использовать необязательный класс.
Чтобы найти 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();
}
Теперь его использование:
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();
}
}
Ответ №4:
Здесь мы можем использовать функцию, подобную этой:
Чтобы найти все объекты с определенным codeIsIn:
public static List<Item> findBycodeIsin(Collection<Carnet> listCarnet, String codeIsIn) {
return items.stream().filter(item -> codeIsIn.equals(item.getCodeIsIn()))
.collect(Collectors.toList());
}
Чтобы найти один элемент (если codeIsIn уникален для каждого объекта):
public static Carnet findByCodeIsIn(Collection<Carnet> listCarnet, String codeIsIn) {
return listCarnet.stream().filter(carnet-> codeIsIn.equals(carnet.getCodeIsIn()))
.findFirst().orElse(null);
}
Ответ №5:
Вот решение с использованием 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
}
Ответ №6:
Вот другое решение, использующее Guava в Java 8, которое возвращает соответствующий элемент, если он существует в списке. Если сопоставляется более одного элемента, сборщик выдает исключение IllegalArgumentException. Если совпадение отсутствует, возвращается значение null.
Carnet carnet = listCarnet.stream()
.filter(c -> c.getCodeIsin().equals(wantedCodeIsin))
.collect(MoreCollectors.toOptional())
.orElse(null);
Ответ №7:
Следуя ответу Олега, если вы хотите найти ВСЕ объекты в списке, отфильтрованном по свойству, вы могли бы сделать что-то вроде:
//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()));
}
}
}
и аналогично, если вы хотите отфильтровать ВСЕ элементы в HashMap с определенным свойством
//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()));
}
}
Комментарии:
Ответ №8:
Для поиска объектов, которые по существу равны, вам необходимо переопределить equals
hashcode
методы и для класса. Вы можете найти хороший учебник здесь.
http://www.thejavageek.com/2013/06/28/significance-of-equals-and-hashcode/