【问题标题】:How do I access the field of an item in a generic arraylist of objects in java?java - 如何访问java中对象的通用arraylist中的项目字段?
【发布时间】:2015-04-12 02:31:10
【问题描述】:

对于分配,我正在尝试编写一种方法,该方法搜索多个 ArrayList 之一(每个 ArrayList 包含不同的对象集合)并将具有匹配“名称”字段的对象返回到指定的对象。我可以通过实现一个函数来搜索一种对象的预设数组列表“_content”,如下所示:

public static Data findContent(String name) {
        for (int i = 0; i < _content.size(); i++ ) {
            if (name.equals(((_content).get(i))._name)) {
                return ((_content).get(i));
            }
        }
        return null;
    }

如果找不到,则返回具有匹配名称字段的第一个对象或 null。 我想使用泛型类型来拥有一种可以搜索不同对象的多个不同列表的方法(每个列表中的每个对象都有一个“名称”字段)。我该怎么做呢?

提前致谢

【问题讨论】:

    标签: java generics arraylist field


    【解决方案1】:

    只是将其添加为一种方法,因为我还没有编译它或我还在平板电脑上输入的任何内容,所以请原谅任何轻微的拼写错误,如果他们被指出,我会更正它们。但是....

    在 OO 中,推荐的方法是封装您的对象,这样您就不会直接使用字段,而是使用访问器方法。

    public String Name (){
        return name;
    }
    

    然后你可以创建一个界面

    public interface DataI {
        String getName ();
    }
    

    您的数据对象将是

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

    完成后,您的通用方法将类似于。

    public static <T extends DataI> T findContent(String name, List<T> content) {
        for (int i = 0; i < content.size(); i++ ) {
            if (name.equals(((content).get(i)).getName())) {
                return ((content).get(i));
            }
        }
        return null;
    }
    

    字符串&lt;T extends DataI&gt; 定义了泛型类型T 以供在方法中使用。

    当 T 扩展 DataI 时,只有实现了 DataI 的类才能满足约束,因此这些类都需要 getName () 方法。

    在某些情况下,您可能需要将列表参数更改为 List&lt;? extends T&gt;。取决于你想在你的方法中做什么。有关于为什么会这样的讨论,我不会在这里讨论。

    【讨论】:

    • 你的回答比我的更详细(+1)。我最初的回答中有List&lt;? extends T&gt;,但后来我意识到在这种情况下它不再是通用的了。这两个签名接受完全相同的东西。
    • 我认为当您想要传递一个额外的参数时需要扩展,该参数是插入列表的候选者以及列表本身。我现在不在 IDE 面前,所以我无法获得这方面的详细信息,我不记得它是如何进行的。
    【解决方案2】:

    您首先需要一个带有方法name 的接口。

    interface NamedThing {
    
        String name();
    }
    

    那么你可以使用泛型方法

    public static <T extends NamedThing> T find(Collection<T> collection, String name) {
        for (T t : collection)
            if (t.name().equals(name))
                return t;
        return null;
    }
    

    为简单起见,我没有在此答案中使用任何 null 检查。

    如果您使用的是 Java 8,则该方法变为单行:

    public static <T extends NamedThing> T find(Collection<T> collection, String name) {
        return collection.stream().filter(t->t.name().equals(name)).findFirst().orElse(null);
    }
    

    【讨论】:

      【解决方案3】:

      如果您使用的是 Java8,我建议为此采用java.util.function.Function

      public static <T> T findContent(List<T> a, String name, java.util.function.Function<T, String> nameOf) {
        for (T e: a) {
          if (nameOf.apply(e).equals(name)) return e;
        }
        return null;
      }
      

      例如一个用法。

      static class Data {
        private String name;
        public Data(String name) {
          this.name = name;
        }
        public String getName() { return name; }
      }
      
      // Assuming `import java.util.*` above.
      public static void main(String[] args) {
        System.err.println("result: "+ findContent(
          Arrays.asList(
            new Data("a"),
            new Data("b"),
            new Data("c")
          ),
          "b",
          Data::getName // Passing an accessor to Data#name as a lambda expression
        ));
      }
      

      从“设计模式”的角度来看,在#3 处传递给nameOf 的lambda 表达式可以被认为是从某个类T 中获取名称的“适配器”。当一个类不能修改时,“适配器模式”非常有用,可以适应现有的模块。

      对不起,我的英语不好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-09
        • 2017-09-27
        • 2016-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多