Collection中的list查找

集合

最近在学习集合相关的东西,今天在玩list的时候发现了两个奇怪的情况,先上第一个情况

IndexOutOfBoundsException

代码如下:

public class TestCollection {
    public static void main(String[] args) {
        List l1 = new LinkedList();
        l1.add(0,"3");
        l1.add(1,"321");
        l1.add(2,"3213");
        l1.add(5,"3261");
        l1.add(3,"3241");
        l1.add(4,"3221");
        System.out.println(l1);
        }
}

控制台输出

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 5, Size: 3
	at java.util.LinkedList.checkPositionIndex(LinkedList.java:560)
	at java.util.LinkedList.add(LinkedList.java:507)
	at Test.TestCollection.main(TestCollection.java:14)

Process finished with exit code 1

先看下错误说明是指下标超出界限,按照我自己之前的理解是,list的add方法,会按照顺序插入相应的元素,但是实际情况好像并不是这样的,因为看5的那个地方发现并没有按照我想象的那样去插入数据,原因是什么呢?我就去看了一下源码----------

/**
     * Inserts the specified element at the specified position in this list.
     * Shifts the element currently at that position (if any) and any
     * subsequent elements to the right (adds one to their indices).
     *
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)
            linkLast(element);
        else
            linkBefore(element, node(index));
    }

上面这一段是插入方法的介绍,首先是一个检查下标的方法,如果下标的数值和list大小数值一样,那么就把它插入到最后一个位置,否则依次插入。

下面详细看一下其中的方法:

    private void checkPositionIndex(int index) {
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

上面这个方法是检查下标的方法,就是第一个先检查下标,一下子就看到了问题所在,和控制台看到的错误一毛一样!!!
根据我的理解是,list的size大小是根据插入的时候扩充的,如果一下子输入超出size的下标,就会产生Exception in thread “main” java.lang.IndexOutOfBoundsException: Index: 5, Size: 3
这样的报错(其中index是下标,size是数组的大小),下标超过了list的大小。
下面是添加元素的方法,感兴趣的可以看一下,不过相信也都实现过了:

    /**
     * Links e as last element.
     */
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
    /**
     * Inserts element e before non-null Node succ.
     */
    void linkBefore(E e, Node<E> succ) {
        // assert succ != null;
        final Node<E> pred = succ.prev;
        final Node<E> newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
    }

感觉自己对集合的理解还是不够,所以产生了这样的错误,根据我的理解,如果事先设定好list的大小,就能避免这个问题。

下标查找错误

感觉这个问题就非常有意思了
先看一下代码:

public class TestCollection {
    public static void main(String[] args) {
        List l1 = new LinkedList();
        l1.add(0,"3");
        l1.add(1,"321");
        l1.add(2,"3213");
        l1.add(3,"3241");
        l1.add(4,"3221");//为什么这个位置的查找失败,根据index查找
        l1.add(5,"3261");
     	l1.remove(1);
        System.out.println(Collections.binarySearch(l1,"3241"));
        System.out.println(Collections.binarySearch(l1,"3221"));
        System.out.println(Collections.binarySearch(l1,"3261"));
        System.out.println(l1);
    }
}

再看一下控制台输出

2
-3
4
[3, 3213, 3241, 3221, 3261]

Process finished with exit code 0

移除一个元素之后,发现除了***l1.add(4,“3221”)***前后输出的下标位置都正确,只有这个不正确,而且有点离谱,先去看一下源码逻辑

public static <T>
    int binarySearch(List<? extends Comparable<? super T>> list, T key) {
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);
    }

判断集合是否是RandomAccess的实例,并且sizi小于5000;
如果是,那就按照按index(小标)查找,如果不是那就iterator(迭代查找),我们是第一个,跟进去

private static <T>
    int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
        int low = 0;
        int high = list.size()-1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            Comparable<? super T> midVal = list.get(mid);
            int cmp = midVal.compareTo(key);

            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found
    }

上面这些代码就是具体的查找逻辑,先定义一个高低(虽然并不知道为什么这么定义,感觉max和min更合适一点)其中初始值low为0,high为size的大小,本程序high为5,然后运算取mid,然后比较获取到的值midVal和key,这个k就是我们list的第二个值,然后返回取cmp,然后运算的到cmp为-3,得到这个结果,解释说list的查找,不但与index有关,与后面的key也有关系,key也应该按顺序排列,这是我的理解,但是总感觉不对,这个样子的代码岂不是存在这样的一个bug,或者也可能是我对集合的了解还是不够深入吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Collection 是 Java 的一个接口,它是所有集合类的父接口。它提供了一些通用的方法,比如 add()、remove()、isEmpty() 等等。 Collection 接口本身并不提供查找的功能。但是在其子接口 List 和 Set ,可以使用 indexOf()、contains() 等方法来实现查找功能。 List 接口提供了根据下标查找元素的方法 get(),也提供了根据元素查找下标的方法 indexOf()。 Set 接口提供了判断是否包含某个元素的方法 contains()。 除此之外,Java 还有一些集合类,如 Map、HashMap、TreeMap 等,它们提供了根据键值对进行查找的功能。 ### 回答2: Collection在实现查找的功能上提供了多种方法,下面将介绍其几种常用的方法: 1. contains(Object obj): 这个方法用于判断集合是否包含某个指定的元素,如果包含则返回true,否则返回false。 2. containsAll(Collection<?> c): 这个方法用于判断集合是否包含指定集合的所有元素,如果都包含则返回true,否则返回false。 3. equals(Object obj): 这个方法用于判断两个集合是否相等,即两个集合的元素是否完全相同且顺序一致。 4. indexOf(Object obj): 这个方法用于查找指定元素在集合的位置,如果找到则返回该元素的索引值,如果没有找到则返回-1。 5. lastIndexOf(Object obj): 这个方法用于查找指定元素在集合最后出现的位置,如果找到则返回该元素的索引值,如果没有找到则返回-1。 6. toArray(): 这个方法用于将集合转换为数组,方便进行遍历和查找操作。 通过以上的方法,我们可以方便地在集合进行元素的查找操作。这些方法可以根据具体的需求灵活使用,根据返回的结果判断元素是否存在于集合,并可以在找到元素后获取其索引值或进行其他相关操作。值得注意的是,这些方法的实现逻辑可能不同,具体的实现效果可能有所差异,因此在使用时需要注意选择合适的方法来满足实际需求。 ### 回答3: Collection是Java的接口,它提供了一组方法来处理一组对象。在Collection接口,并没有单独提供查找的方法,但是可以通过迭代器或者其他集合类的方法来实现查找的功能。 首先,可以使用Iterator迭代器来遍历集合的元素,然后利用条件判断来查找指定的元素。通过调用集合对象的iterator()方法,可以获得一个Iterator对象,然后利用while循环和hasNext()方法遍历集合的元素,使用next()方法获取每个元素,再通过条件判断来找到需要的元素。 其次,可以使用ArrayList或者其他实现了Collection接口的具体类的contains()方法来判断集合是否包含指定的元素。contains()方法会遍历集合的元素,使用equals()方法对比每个元素和传入的对象是否相等,如果找到相等的元素,则返回true,否则返回false。 此外,还可以使用其他集合类的方法来实现查找功能。例如,可以使用HashMap的get()方法来根据键来查找对应的值,或者使用LinkedList的indexOf()方法来查找指定元素第一次出现的位置等。 总而言之,Collection接口本身并没有提供查找的方法,但是可以通过迭代器、contains()方法以及其他集合类的方法来实现查找功能,根据具体的需求选择合适的方法来进行查找

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值