【问题标题】:How can I extract values from a list of objects based on a property of these objects?如何根据这些对象的属性从对象列表中提取值?
【发布时间】:2016-06-19 07:21:48
【问题描述】:

我想根据某个属性在列表中查找对象。

例如,假设我有一个此类的对象列表:

class Person {
    private String name;
    private String id;
}

我知道我可以通过以下方式获取列表中的所有人的姓名:

Collection<String> names = CollectionUtils.collect(
    personList,
    TransformerUtils.invokerTransformer("getName"));  

但我想做的是获取名称为"Nick"Person 对象的列表。我没有 Java 8。

【问题讨论】:

  • 简单地遍历列表并检查每个名称有什么问题?
  • 使用 for 语句迭代列表,在内部检查名称是否等于 'Nick',如果是,则将对象添加到另一个列表中
  • for 循环和 if 语句始终存在。
  • 使用 java 8 流式 API 中的过滤器会更好,但性能可能不如 for 外观。类似List&lt;Person&gt; nicks = personList.stream.filter(person-&gt; "Nick".equals(person.getName()).collect(Collectors.toList())
  • 当您可以简单地遍历列表并检查名称是否为“Nick”时,为什么要使用集合来执行此操作。

标签: java list collections


【解决方案1】:

我看到你正在使用 Apache Common Utils,那么你可以使用:

CollectionUtils.filter( personList, new Predicate<Person>() {
    @Override
    public boolean evaluate( Person p ) {
        return p.getName() != null && p.getName().equals( "Nick" );
    }
});

【讨论】:

  • return "Nick".equals(p.getName());
  • Apache 集合实用程序提供了将转换器转换为谓词的方法,因此不需要匿名类(假设 OP 愿意使用其代码示例所示的反射)。
  • @svasa 非常感谢。
【解决方案2】:

如果您不想使用 Java 8 流,只需遍历列表并手动检查元素:

ArrayList<Person> filteredList = new ArrayList<Person>();

for(Person person : personList) {
    if(person.getName().equals("Nick")) filteredList.add(person);
}

【讨论】:

    【解决方案3】:

    使用 Apache 集合实用程序(您已经在使用),您可以使用 filter 方法创建集合的子集,其中包含与给定过滤器匹配的项目,以及与“尼克”匹配的 Predicate基于您的TransformertransformedPredicate

    CollectionUtils.filter(names, PredicateUtils.transformedPredicate(
        TransformerUtils.invokerTransformer("getName"), PredicateUtils.equalPredicate("Nick")));
    

    也就是说,在迁移到 Java 8 之前,您可能需要重新考虑使用这种功能强大的方法。迁移后您不仅会有大量冗余的 Apache 集合代码,而且在引入闭包和 lambda 之前的解决方案与命令式替代方案相比,往往冗长且可读性差。

    注意: 这会就地修改现有集合。如果这不是所需的行为,则需要在调用过滤器方法之前创建一个副本。

    【讨论】:

    • 您的代码似乎删除了所有结果,而不仅仅是我要提取的结果
    • 它应该可以工作,尽管可能存在错误(我没有尝试过)。你能发布一个显示它不起作用的 SSCCE 吗?
    • 当然。一会儿我会发。
    • 我实际上弄清楚了为什么它不起作用。你的代码是绝对正确的。非常感谢。赞成。
    【解决方案4】:

    您可以尝试使用 HashMap。

    HashMap<String, Integer> points = new HashMap<String, Integer>();
        points.put("Amy", 154);
        points.put("Dave", 42);
        points.put("Rob", 733);
        System.out.println(points.get("Dave")); 
    

    这只是一个示例,但您可以检查,而不是使用 String、Integer,您可以尝试使用 Integer、String 并使用 if statement。不过只是一个想法。

    【讨论】:

      【解决方案5】:

      我正在考虑您可能拥有具有此属性名称的不同对象的集合。为此,我建议您为这些组件做父并使用泛型对其执行搜索:

      例如:

      父类名.java

      public class Name {
      
          private String name;
      
          public Name(String name) {
              this.name = name;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      }
      

      类 Pet.java

      public class Pet extends Name{
      
          public Pet(String name) {
              super(name);
          }
      
      }
      

      还有类 Person.java

      public class Person extends Name{
      
          public Person(String name) {
              super(name);
          }
      
      }
      

      没有该属性的作业类:

      public class Job {
      
          private String description;
      
          public Job(String description) {
              this.description = description;
          }
      
          public String getDescription() {
              return description;
          }
      
          public void setDescription(String description) {
              this.description = description;
          }
      
      }
      

      有了它,你可以检查它的实例并比较你想要的:

      public static void main(String ... args) {
          List<Object> objectList = new ArrayList();
          objectList.add(new Person("Nick"));
          objectList.add(new Person("Nik"));
          objectList.add(new Person("Nikc"));
          objectList.add(new Person("Ncik"));
          objectList.add(new Pet("Nick"));
          objectList.add(new Pet("Nik"));
          objectList.add(new Pet("Nikc"));
          objectList.add(new Pet("Ncik"));
          objectList.add(new Job("Nick"));
          objectList.add(new Job("Nik"));
          objectList.add(new Job("Nikc"));
          objectList.add(new Job("Ncik"));
      
          for (Object o : extractObjectsMatching("Nick", objectList)){
              System.out.println(((Name) o).getName());
          }
      }
      
      public static List<Object> extractObjectsMatching(String name, List<Object> objectList){
          List<Object> matches = new ArrayList<>();
          for (Object e : objectList){
              if (e instanceof Name && ((Name) e).getName().contains(name)){
                  matches.add(e);
              }
          }
      
          return matches;
      }
      

      如果 Object 类不是 Name 的实例,则表示不具有您要查找的属性,请忽略,否则,与您要检索的信息进行比较并存储检索。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-25
        • 1970-01-01
        • 1970-01-01
        • 2019-04-16
        • 1970-01-01
        • 2019-03-09
        • 2022-01-11
        相关资源
        最近更新 更多