通过传递泛型参数获取ArrayList中的项索引

时间:2017-07-21 09:37:28

标签: java generics arraylist

我需要创建一个方法,通过比较其中一个字段来返回列表中对象的索引。 我有2个A类和B类,其中包含覆盖Equals()HashCode()方法:

A类:

public class A {
 private String field1;
 private String field2;
 //getters and setters
 @Override
 public boolean equals (Object o){
  if (this == o) return true;
  if (o == null || getClass() != o.getClass()) return false;
  if (!super.equals(o)) return false;
  A that = (A) o;
  return field1.equals(that.field1);
 }

  @Override
  public int hashCode() {
   int result = super.hashCode();
   result = 31 * result + field1.hashCode();
   return result;
  }
}

B组:

public class B {
 private String field1;
 private String field2;
 //getters and setters
 @Override
 public boolean equals (Object o){
  if (this == o) return true;
  if (o == null || getClass() != o.getClass()) return false;
  if (!super.equals(o)) return false;
  B that = (B) o;
  return field2.equals(that.field2);
 }

  @Override
  public int hashCode() {
   int result = super.hashCode();
   result = 31 * result + field2.hashCode();
   return result;
  }
}

在我的主程序中,我需要实现一个泛型方法,该方法返回A或B ArrayList<>内项的索引。

private int getObjectIndexFromList(List<A or B> list, A or B param){
  int index;
  try{
    index = list.indexOf(list.stream().filter(e -> e.equals(param)));
  }catch (NoSuchElementException ex){
    index = -1;
  }
  return index;
}

所以我的问题是如何为该方法传递通用参数?

2 个答案:

答案 0 :(得分:1)

我假设您要与A.field1A.field2B.field1B.field1进行比较?

在这种情况下,您可以使用lambda在流中找到它。像这样:

private <T> int getObjectIndexFromList(List<T> list, Predicate<T> predicate){
    int index;
    try {
        index = list.indexOf(list.stream()
                .filter(predicate)
                .findFirst()
                .get());
    } catch (NoSuchElementException ex){
        index = -1;
    }
    return index;
}

然后你就这样使用它:

int index = getObjectIndexFromList(listOfAs, a -> a.field1.equals("foo"));

在这里使用流并不是最佳的,因为您有效地遍历列表两次并检查参数和搜索对象的相等性。使用跟踪当前索引的列表迭代器会更有效:

private <T> int getObjectIndexFromList(List<T> list, Predicate<T> predicate){
    ListIterator<T> it = list.listIterator();
    while (it.hasNext()) {
        // Get the item and it's index in the list
        int index = it.nextIndex();
        T item = it.next();
        if (predicate.test(item)) {
            // We found it, return the index
            return index;
        }
    }
    // We didn't find anything
    return -1;
}

以下是使用中的示例:

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("foo");
    list.add("bar");
    list.add("foobar");
    list.add("fubar");
    list.add("Hello World!");
    System.out.printf("String with length %s has index %s%n",
            5, getObjectIndexFromList(list, s -> s.length() == 5));
}

输出:

  

长度为5的字符串具有索引3

答案 1 :(得分:0)

如果您有覆盖哈希码并且等于方法...为什么不打电话给&#39; List.indexOf&#39;?

让他们扩展相同的抽象类(我不知道确切的问题,但如果他们在同一个列表中结束很可能他们将结束为家庭)并使用它。

IndexOf使用&#39; equals&#39;找到对象的索引,所以它必须工作...