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

Java 通过传递泛型参数获取ArrayList中的项索引,java,generics,arraylist,Java,Generics,Arraylist,我需要创建一个方法,通过比较列表中某个对象的字段来返回该对象的索引。 我有两个类A和B,它们被重写了Equals()和HashCode()方法,如下所示: int index = getObjectIndexFromList(listOfAs, a -> a.field1.equals("foo")); A类: public class A { private String field1; private String field2; //getters and setters

我需要创建一个方法,通过比较列表中某个对象的字段来返回该对象的索引。 我有两个类A和B,它们被重写了
Equals()
HashCode()
方法,如下所示:

int index = getObjectIndexFromList(listOfAs, a -> a.field1.equals("foo"));
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;
}
private int getObjectIndexFromList(列表,A或B参数){
整数指数;
试一试{
index=list.indexOf(list.stream().filter(e->e.equals(param));
}捕获(无接触元素例外){
指数=-1;
}
收益指数;
}

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

如果您有覆盖hashcode和equals方法。。。为什么不直接调用“List.indexOf”

让他们扩展同一个抽象类(我不知道确切的问题是什么,但如果他们的结尾在同一个列表中,他们很可能会成为一个家族)并使用它


IndexOf使用“equals”查找对象的索引,因此它必须工作…

我假设您想与
A.field1
A.field2
B.field1
B.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;
}
不过,在这里使用流并不是最优的,因为您实际上要遍历列表两次,并检查参数和所搜索对象的相等性。使用跟踪当前索引的列表迭代器更有效:

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;
}
private int getObjectIndexFromList(列表列表,谓词){
ListIterator it=list.ListIterator();
while(it.hasNext()){
//获取列表中的项目及其索引
int index=it.nextIndex();
T item=it.next();
if(谓词测试(项目)){
//我们找到了,返回索引
收益指数;
}
}
//我们什么也没找到
返回-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));
}
publicstaticvoidmain(字符串[]args){
列表=新的ArrayList();
列表。添加(“foo”);
列表。添加(“酒吧”);
列表。添加(“foobar”);
列表。添加(“fubar”);
添加(“你好,世界!”);
System.out.printf(“长度为%s的字符串具有索引%s%n”,
5,getObjectIndexFromList(列表,s->s.length()=5);
}
以及输出:

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


A和B之间的关系是什么?如果没有,接口就是你的朋友。你为什么需要这种方法呢?只需使用
list。indexOf(element)
@Eran OP只想传递一个同时满足列表签名的列表。@Eran就像Suresh Atta告诉你的那样,我需要对A和B的列表使用该方法。@SureshAtta你能再解释一下在这种情况下如何使用接口吗?我预先设置了第二个解决方案,因为它更优化。但是我只想知道为什么
a->a.equals(tmpA)
即使在重写
equals()
HashCode()
methods之后仍然返回-1,而不必在可执行示例中看到所有代码。您确定在
equals
中签入的所有字段确实相等吗?我正在记录项.getFieldA(),其值为equal使用调试器运行它,查看哪一行导致equals返回false,问题不在于如何找到项目索引的算法,而是如何在每次需要调用此方法时传递不同类型的列表和项目。