使用列表获取匹配项目索引的有效方法

时间:2011-08-18 12:30:36

标签: java collections arraylist

我有两个列表A和B.我想找出A中与listB元素匹配的元素索引。像这样:

ArrayList listA = new ArrayList();
listA.add(1);listA.add(2);listA.add(3);listA.add(4);
ArrayList listB = new ArrayList();
listB.add(2);listB.add(4);
ArrayList listC = new ArrayList();
for(int i=0; i<listB.size();i++) {
   int element = listB.get(i);
   for(int j=0; j<listA.size(); j++) {
      if(listA.get(j) == element) listC.add(j);
   }
}

我想这是一种难看的方式。找到与B中所有元素匹配的A的所有索引的最佳方法是什么?我相信在集合api中存在一个名为containsAll的方法 - 不要认为它返回匹配的索引。

6 个答案:

答案 0 :(得分:6)

如果您必须使用ArrayList,则可以从HashSet创建ArrayList。这将调用contains O(1)。创建HastSet需要O(n)。如果你可以从HashSet开始,那将是最好的。

public static void main(String[] args) 
{
    List listA = new ArrayList();
    listA.add(1);
    listA.add(2);
    listA.add(3);
    listA.add(4);
    List listB = new ArrayList();
    listB.add(2);
    listB.add(4);
    Set hashset = new HashSet(listA);

    for(int i = 0; i < listB.size(); i++) 
    {
        if(hashset.contains(listB.get(i))) 
        {
            listC.add(i);
            System.out.println(i);
        }
    }   
}

答案 1 :(得分:2)

Guava库带有方法

"SetView com.google.common.collect.Sets.intersection(Set a, Set b)

将给出两个集合中包含的元素,但不包含索引。虽然事后应该很容易获得索引。

答案 2 :(得分:1)

简单:

List<Integer> listA = new ArrayList<Integer>();
listA.add(1);
listA.add(2);
listA.add(3);
listA.add(4);

List<Integer> listB = new ArrayList<Integer>();
listB.add(2);
listB.add(4);

List<Integer> listC = new ArrayList<Integer>();

for ( Integer item : listA ) {
    int index = listB.indexOf( item );
    if ( index >= 0 ) {
        listC.add(index);
    }
}

但这仅在没有重复时有效,如果有重复索引,则必须按照您的方式进行,导航完整列表。

修改

我认为你想要的是元素,而不是索引,集合不会给你索引,只有元素。

答案 3 :(得分:1)

假设没有重复的值,为什么不使用ArrayList.indexOf


public final class ArrayListDemo {
    public static void main(String[]args){
        findIndices(createListA(), createListB());      
    }

    private static final List<Integer> createListA(){
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(3);
        list.add(5);

        return list;
    }

    private static final List<Integer> createListB(){
        List<Integer> list = new ArrayList<Integer>();
        list.add(0);
        list.add(2);
        list.add(3);
        list.add(4);

        return list;
    }

    private static void findIndices(List<Integer> listA, List<Integer> listB){
        for(int i = 0; i < listA.size(); i++){  
            // Get index of object in list b
            int index = listB.indexOf(listA.get(i));

            // Check for match
            if(index != -1){
                System.out.println("Found match:");
                System.out.println("List A index = " + i);
                System.out.println("List B index = " + index);
            }
        }
    }
}

<强>输出

Found match:
List A index = 1
List B index = 2

答案 4 :(得分:1)

如果列表A和列表B按相同的顺序排序(我假设升序,但降序也起作用),这个问题有一个O(n)解决方案。下面是一些(非正式的,未经测试的)代码。当循环退出时,indexMap应该包含列表A中与列表B中的元素匹配的每个元素的索引以及列表B中匹配元素的索引。

  int currentA;
  int currentB;
  int listAIndex = 0;
  int listBIndex = 0;
  Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>();

  currentA = listA.get(listAIndex);
  currentB = listB.get(listBIndex);
  while ((listAIndex < listA.length) && (listBIndex < listB.length))
  {
    if (currentA == currentB)
    {
      indexMap.put(listAIndex, listBIndex);
      ++listAIndex;
    }
    else if (currentA < currentB)
    {
      ++listAIndex;
    }
    else // if (currentA > currentB)
    {
      ++listBIndex;
    }
  }

答案 5 :(得分:0)

使用Apache CollectionUtils,有很多选项