【问题标题】:How to find an object in an ArrayList by property如何通过属性在 ArrayList 中查找对象
【发布时间】:2013-07-05 18:48:29
【问题描述】:

我如何在知道其属性codeIsinArrayList<Carnet> 中找到对象Carnet

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

public class Carnet {

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

    // Setters and getters

}

【问题讨论】:

  • indexOf(),前提是您的对象覆盖equals()
  • 类 Carnet 在 jar 文件中我无法覆盖 equals()
  • 如果我是你,我会从任何地方找到源代码,并得到它的 equals 和 hashCode 实现。唯一的另一种选择是手动迭代 Collection 并检查成员是否相等。
  • 我宁愿使用地图而不是列表。如果您经常寻找对象并且性能是一个问题,那么排序的地图可能会更好。在我看来,为此目的实现和使用 equal 是丑陋的。
  • 对于 Java 8,您可以从 ArrayList 获取流并对其应用 filter(e->e.codeIsIn.equals(...))。

标签: java arraylist collections


【解决方案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

    覆盖Carnetequals() 方法。

    选项 3

    将您的List 存储为Map,使用codeIsIn 作为键:

    HashMap<String, Carnet> carnets = new HashMap<>();
    // setting map
    Carnet carnet = carnets.get(codeIsIn);
    

    【讨论】:

    • 我没有得到 Option2。我覆盖equals() 然后做什么?
    • @idclev463035818 我猜使用ArrayList.indexOf 方法
    • 您可以覆盖 equals() 方法,该方法将确保当一个对象的此特定字段(在本例中为 codeIsin)等于另一个对象中的相同字段时,它们认为相等。然后,您可以使用此字段和相同的值(与您要查找的对象中的相同)创建一个对象,并按如下方式搜索列表:listCarnet.get(listCarnet.indexOf(OBJECT YOU HAVE JUST CREATED))。跨度>
    【解决方案3】:

    如果您使用 Java 8 并且您的搜索可能返回 null,您可以尝试使用 Optional 类。

    要查找通行证:

    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】:

      这是使用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
      }
      

      【讨论】:

        【解决方案5】:

        这是在 Java 8 中使用Guava 的另一种解决方案,如果列表中存在匹配元素,则返回匹配的元素。如果匹配多个元素,则收集器将抛出 IllegalArgumentException。如果没有匹配,则返回 null

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

        【讨论】:

          【解决方案6】:

          在这里,我们可以使用这样的函数:

          要查找所有具有特定 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);
          }
          

          【讨论】:

            【解决方案7】:

            按照 Oleg 的回答,如果您想在按属性过滤的 List 中查找 ALL 对象,您可以执行以下操作:

            //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 中的 ALL 项目

            //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】:

            要查找有意义相等的对象,您需要覆盖该类的equalshashcode 方法。你可以在这里找到一个很好的教程。

            http://www.thejavageek.com/2013/06/28/significance-of-equals-and-hashcode/

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-09-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-07-31
              • 1970-01-01
              • 2011-08-18
              相关资源
              最近更新 更多