尚硅谷-集合笔记3

本文详细分析了Java集合框架中ArrayList、LinkedList和Vector的实现原理与异同。讨论了它们的存储结构、性能特点以及在JDK不同版本中的变化。此外,还展示了List接口中常用方法的使用示例,包括遍历、添加、删除、修改等操作。文章最后探讨了迭代器和增强for循环的遍历方式。
摘要由CSDN通过智能技术生成
package com.atgugui.java;

import org.junit.Test;

import java.util.*;

/**
 ** 1. /----Collection接口:单列集合,用来存储一个一个的对象
 *       /---List接口(JDK1.2):存储有序的,可重复的数据。  -->“动态”数组,替换原有的数组(因为原来的数组一旦确定长度不可变化,这个不确定长度直接添加元素即可)
 *           /---ArrayList(JDK1.2):作为List接口的主要实现类,线程不安全,效率高;底层使用Object[] elementData数组
 *           /---LinkedList(JDK1.2):对于频繁的插入、删除操作,使用此类比Array list高;底层使用的是双向链表存储
 *           /---Vector(JDK1.0):作为List接口的古老实现类,线程安全的,效率低;底层使用Object[] elementData数组
 *
 *
 *2. ArrayList的源码分析:
 * 2.1 JDK 7 情况下:
 *    ArrayList list=new ArrayList();//底层创建了长度是10的Object[] 数组elementDate
 *    list.add(123);//elementData[0]=new Integer(123);;;;;;;;;;;;;;
 *    .....
 *    list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。
 *    默认情况下,扩容为原来容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。
 *
 *    结论:建议开发中使用带参的构造器:ArrayList list=new ArrayList(int capacity);//避免在中间环节去扩容,这样效率更高一些。
 *
 * 2.2 JDK 8 情况下ArrayList:
 *    ArrayList list=new ArrayList();//底层Object[] elementData初始化为{},并没有创建长度为10的数组
 *
 *    list.add(123);//第一次调用add()时,底层才创建了长度为10的数组,并将数据123添加到elementData[0]
 *    ...
 *    后续的添加和扩容操作与JDK7 无异。
 *2.3 小结:
 *    jdk 7中的ArrayList的对象的创建类似于单例模式的饿汉式,而JDK8中的ArrayList的对象的创建类似于单例的懒汉式,延迟了数组的创建,节省内存。
 *
 *
 *
 * 3. LinkedList的源码分析:
 *    LinkedList list=new LisnkedList();内部声明了Node类型的first和last属性。默认值为null
 *     list.add(123);//将123封装到Node中,创建了Node对象。
 *
 *     其中,Node定义为:体现了LinkedList的双向链表的说法
 *      private static class Node<E> {
 *     E item;
 *     Node<E> next;
 *     Node<E> prev;
 *     Node(Node<E> prev, E element, Node<E> next) {
 *     this.item = element;
 *     this.next = next;
 *     this.prev = prev;
 *     }
 *     }
 *
 *
 *  4.Vector的源码分析:JDK7 和JDK8中通过Vector()创建对象时,底层都创建了长度为10 的数组
 *    在扩容方面,默认扩容为原来的数组长度的2倍。
 *
 *     面试题:ArrayList、LinkedList、Vector三者的异同?
 *     同:这三个类都实现了List接口,存储数据的特点形同:存储有序的、可重复的数据
 *     不同点:上面!!
 * 5. List接口中常用方法
 * void add(int index, Object ele):在index位置插入ele元素
 * boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
 * Object get(int index):获取指定index位置的元素
 * int indexOf(Object obj):返回obj在集合中首次出现的位置
 * int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
 * Object remove(int index):移除指定index位置的元素,并返回此元素
 * Object set(int index, Object ele):设置指定index位置的元素为ele
 * List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
 *
 * 常用方法总结:
 * 增:add(Object obj)
 * 删:remove(int index):自己定义 / remove(Object obj)Collection集合中的
 * 改:set(int index,Object ele)
 * 查:get(int index)
 * 插:add(int index,Object ele)
 * 长度:size()
 * 遍历:①Iterator迭代器;②增强for循环;③普通循环(用索引)
 *
 *
 * @author WZ
 * @create 2021-06-24 22:48
 */
public class ListTest {

    /*List接口中常用的方法
   void add(int index, Object ele):在index位置插入ele元素
   boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
   Object get(int index):获取指定index位置的元素
   int indexOf(Object obj):返回obj在集合中首次出现的位置
   int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
   Object remove(int index):移除指定index位置的元素,并返回此元素
   Object set(int index, Object ele):设置指定index位置的元素为ele
   List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
     */
    @Test
    public void test3(){
        ArrayList list=new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        //方式一:使用Iterator迭代器进行遍历
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());

        }
        System.out.println("*********************");
        //方式二:使用增强for循环进行遍历
        for(Object obj:list){
            System.out.println(obj);
        }
        System.out.println("*********************");
        //方式三:使用普通for循环
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }


    }
    @Test
    public void test2(){
        ArrayList list=new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add(new Person("Tom",12));
        list.add(456);

        //方法四:int indexOf(Object obj):返回obj在集合中首次出现的位置;如果不存在返回-1
        int index = list.indexOf(456);
        System.out.println(index);//若有,返回相应的位置,若没有则返回-1;

        //方法五:int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置;如果不存在返回-1
        int index1 = list.lastIndexOf(456);
        System.out.println(index1);//4

        //方法六:Object remove(int index):移除指定index位置的元素,并返回此元素
        Object obj = list.remove(0);//把第一个元素给删除,这个是用的索引位置删除,还有直接删除里面的元素方法。所以remove有两个特别注意!!!
        System.out.println(obj);//123;删除之后后面的往前移
        System.out.println(list);//[456, AA, Person{name='Tom', age=12}, 456]

        //方法七:Object set(int index, Object ele):设置指定index位置的元素为ele,并返回此元素
        list.set(1, "CC");//和上面remove一样,并返回此元素
        System.out.println(list);//[456, CC, Person{name='Tom', age=12}, 456]

        //方法八:List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合;(左闭右开区间)

        List list1 = list.subList(2, 4);
        List list2 = list.subList(1, 3);
        System.out.println(list1);
        System.out.println(list2);


    }

    @Test
    public void test1(){
        ArrayList list=new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add(new Person("Tom",12));
        list.add(456);

        System.out.println(list);//[123, 456, AA, Person{name='Tom', age=12}, 456] ;调用了内部重写的toString方法

        //方法1:void add(int index, Object ele):在index位置插入ele元素
        list.add(1,789);//一个一个往后移。789插入到1的位置
        System.out.println(list);//[123, 789, 456, AA, Person{name='Tom', age=12}, 456]

        //方法2:boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
        List list1 = Arrays.asList(1, 2, 3);
        boolean  b = list.addAll(list1);//没有指定索引位置的话默认在最后面添加
        System.out.println(b);//true
        //list.add(list1);//这个也不报错,但是这个是把上面的1,2,3 当成一个元素来进行添加了
        System.out.println(list.size());//9
        System.out.println(list);//[123, 789, 456, AA, Person{name='Tom', age=12}, 456, 1, 2, 3]

        //方法三:Object get(int index):获取指定index位置的元素
        System.out.println(list.get(0));//123


    }






}

3.1增强for循环

package com.atgugui.java;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;

/**
 * JDK 5.0 新增了foreach循环,用于遍历集合、数组
 *
 * @author WZ
 * @create 2021-06-24 22:09
 */
public class ForTest {

    @Test
    public void test1() {
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("Jerry", 20));
        coll.add(new String("Tom"));
        coll.add(false);

        // for(集合中元素的类型 局部变量:集合对象)---集和对象(coll)的元素就是object类型,所以前面是Object,类型得一致
        //其实内部调用的还是迭代器iterator 只是形式上是这样写的
        for (Object obj : coll) {// coll 会自动的取第一个元素,然后赋值给 obj这个类型的变量,然后打印obj,然后再去coll中的第二个元素。。。。。。。等等

            System.out.println(obj);
        }


    }

    @Test
    public void test2() {
        int[] i = new int[]{1, 2, 3, 4, 5, 6};
        // for(数组中元素的类型 局部变量:数组对象)
        for (int inter : i) {
            System.out.println(inter);

        }
    }

    @Test
    public void test3() {
        String[] arr = new String[]{"MM", "MM", "MM"};
        //方式一:普通for赋值
//        for (int i = 0; i < arr.length; i++) {
//            arr[i] = "GG";
//            System.out.println(arr[i]);//GG----这种方式是拿着数组的本身的元素做修改
//        }

        //方式二:增强for循环
        for (String s : arr) {
            s="GG";
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);//MM---这个只是把值赋值给s,s把值给改了,但是数组本身是不变的
        }


    }

}

3.2迭代器interator

package com.atgugui.java;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * 集合元素的遍历操作,使用迭代器Interator接口
 * 1.内部的方法:hasNext() 和 next()
 * 2.集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
 * 3.内部定义了remove()方法,可以在遍历的时候删除集合中的元素。此方法不同于集合直接调用remove()
 * @author WZ
 * @create 2021-06-22 21:23
 */
public class IteratorTest {
    @Test
    public void test1() {
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("Jerry", 20));
        coll.add(new String("Tom"));
        coll.add(false);

        Iterator iterator = coll.iterator();//这个返回Iterator对象的时候可以理解为当前就有一个指针指在第一个添加值的上面,这里就是指在123的上面但是没有指着123
        //当调用iterator.next()方法时,先指针下移指着第一个元素(123),然后把下移以后的元素(123)返回;依次循环直到元素调完为止。

        //方式一:开发中不用
//        System.out.println(iterator.next());//123
//        System.out.println(iterator.next());//456
//        System.out.println(iterator.next());//Person{name='Jerry', age=20}
//        System.out.println(iterator.next());//Tom
//        System.out.println(iterator.next());//false

//        System.out.println(iterator.next());//NoSuchElementException 没有这个元素,就报异常,相当于数组的角标越界

        //方式二:使用for循环+interator.next(); 开发中也不推荐这样写
//        for (int i = 0; i < coll.size(); i++) {
//            System.out.println(iterator.next());
//        }
        //方式三:推荐 使用iterator.hasNext() 与 iterator.Next() 这两个分别搭配使用
        while (iterator.hasNext()) {         //iterator.hasNext()调用这个方法表示判断iterator里面是否还有元素,有元素就进去,没有元素就不进去。
            //next():a.指针下移;b.将下移以后的集合位置上的元素返回
            System.out.println(iterator.next());
        }


    }
    @Test
    public void test2() {
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("Jerry", 20));
        coll.add(new String("Tom"));
        coll.add(false);

        //错误方式一:
//        Iterator iterator = coll.iterator();
//        while ((iterator.next() !=null)){
//            System.out.println(iterator.next());//结果会跳着输出
//        }
        //错误方式二:只要一进循环都会返回一个新的迭代器的对象,所以相当于每次指针都是复位。
        //集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
        while (coll.iterator().hasNext()) {
            System.out.println(coll.iterator().next());//123死循环,因为每调用一次iterator()方法就会返回一个新的迭代器iterator对象,在这里相当于指针复位。
        }

    }

    //测试Iterator中的remove()
    //如果还未调用next()或在上一次调用next方法之后已经调用了remove方法,再调用remove都会报IllegalStateException,remove跟着next指针走
    @Test
    public void test3() {
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("Jerry", 20));
        coll.add(new String("Tom"));
        coll.add(false);

        //删除集合中的"Tom"
        Iterator iterator = coll.iterator();
        while (iterator.hasNext()) {
//            iterator.remove();出错,因为现在指针再最上面,指着空气
            Object obj = iterator.next();
            if ("Tom".equals(obj)) {
                iterator.remove();
//                iterator.remove();出错,现在指针指着的是已经删除的元素,现在也么有元素。
            }
        }

        //遍历集合中的元素
        Iterator iterator1 = coll.iterator();//特别注意:不能拿上面的iterator进行再次遍历因为上面的指针已经指到最后一个了。所以得重新造一个
        //iterator = coll.iterator();
        while (iterator1.hasNext()) {
            System.out.println(iterator1.next());//输出的结果没有Tom
        }
    }
}

3.3List

package com.atgugui.java;

import org.junit.Test;

import java.util.*;

/**
 ** 1. /----Collection接口:单列集合,用来存储一个一个的对象
 *       /---List接口(JDK1.2):存储有序的,可重复的数据。  -->“动态”数组,替换原有的数组(因为原来的数组一旦确定长度不可变化,这个不确定长度直接添加元素即可)
 *           /---ArrayList(JDK1.2):作为List接口的主要实现类,线程不安全,效率高;底层使用Object[] elementData数组
 *           /---LinkedList(JDK1.2):对于频繁的插入、删除操作,使用此类比Array list高;底层使用的是双向链表存储
 *           /---Vector(JDK1.0):作为List接口的古老实现类,线程安全的,效率低;底层使用Object[] elementData数组
 *
 *
 *2. ArrayList的源码分析:
 * 2.1 JDK 7 情况下:
 *    ArrayList list=new ArrayList();//底层创建了长度是10的Object[] 数组elementDate
 *    list.add(123);//elementData[0]=new Integer(123);;;;;;;;;;;;;;
 *    .....
 *    list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。
 *    默认情况下,扩容为原来容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。
 *
 *    结论:建议开发中使用带参的构造器:ArrayList list=new ArrayList(int capacity);//避免在中间环节去扩容,这样效率更高一些。
 *
 * 2.2 JDK 8 情况下ArrayList:
 *    ArrayList list=new ArrayList();//底层Object[] elementData初始化为{},并没有创建长度为10的数组
 *
 *    list.add(123);//第一次调用add()时,底层才创建了长度为10的数组,并将数据123添加到elementData[0]
 *    ...
 *    后续的添加和扩容操作与JDK7 无异。
 *2.3 小结:
 *    jdk 7中的ArrayList的对象的创建类似于单例模式的饿汉式,而JDK8中的ArrayList的对象的创建类似于单例的懒汉式,延迟了数组的创建,节省内存。
 *
 *
 *
 * 3. LinkedList的源码分析:
 *    LinkedList list=new LisnkedList();内部声明了Node类型的first和last属性。默认值为null
 *     list.add(123);//将123封装到Node中,创建了Node对象。
 *
 *     其中,Node定义为:体现了LinkedList的双向链表的说法
 *      private static class Node<E> {
 *     E item;
 *     Node<E> next;
 *     Node<E> prev;
 *     Node(Node<E> prev, E element, Node<E> next) {
 *     this.item = element;
 *     this.next = next;
 *     this.prev = prev;
 *     }
 *     }
 *
 *
 *  4.Vector的源码分析:JDK7 和JDK8中通过Vector()创建对象时,底层都创建了长度为10 的数组
 *    在扩容方面,默认扩容为原来的数组长度的2倍。
 *
 *     面试题:ArrayList、LinkedList、Vector三者的异同?
 *     同:这三个类都实现了List接口,存储数据的特点形同:存储有序的、可重复的数据
 *     不同点:上面!!
 * 5. List接口中常用方法
 * void add(int index, Object ele):在index位置插入ele元素
 * boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
 * Object get(int index):获取指定index位置的元素
 * int indexOf(Object obj):返回obj在集合中首次出现的位置
 * int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
 * Object remove(int index):移除指定index位置的元素,并返回此元素
 * Object set(int index, Object ele):设置指定index位置的元素为ele
 * List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
 *
 * 常用方法总结:
 * 增:add(Object obj)
 * 删:remove(int index):自己定义 / remove(Object obj)Collection集合中的
 * 改:set(int index,Object ele)
 * 查:get(int index)
 * 插:add(int index,Object ele)
 * 长度:size()
 * 遍历:①Iterator迭代器;②增强for循环;③普通循环(用索引)
 *
 *
 * @author WZ
 * @create 2021-06-24 22:48
 */
public class ListTest {

    /*List接口中常用的方法
   void add(int index, Object ele):在index位置插入ele元素
   boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
   Object get(int index):获取指定index位置的元素
   int indexOf(Object obj):返回obj在集合中首次出现的位置
   int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
   Object remove(int index):移除指定index位置的元素,并返回此元素
   Object set(int index, Object ele):设置指定index位置的元素为ele
   List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
     */
    @Test
    public void test3(){
        ArrayList list=new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        //方式一:使用Iterator迭代器进行遍历
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());

        }
        System.out.println("*********************");
        //方式二:使用增强for循环进行遍历
        for(Object obj:list){
            System.out.println(obj);
        }
        System.out.println("*********************");
        //方式三:使用普通for循环
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }


    }
    @Test
    public void test2(){
        ArrayList list=new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add(new Person("Tom",12));
        list.add(456);

        //方法四:int indexOf(Object obj):返回obj在集合中首次出现的位置;如果不存在返回-1
        int index = list.indexOf(456);
        System.out.println(index);//若有,返回相应的位置,若没有则返回-1;

        //方法五:int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置;如果不存在返回-1
        int index1 = list.lastIndexOf(456);
        System.out.println(index1);//4

        //方法六:Object remove(int index):移除指定index位置的元素,并返回此元素
        Object obj = list.remove(0);//把第一个元素给删除,这个是用的索引位置删除,还有直接删除里面的元素方法。所以remove有两个特别注意!!!
        System.out.println(obj);//123;删除之后后面的往前移
        System.out.println(list);//[456, AA, Person{name='Tom', age=12}, 456]

        //方法七:Object set(int index, Object ele):设置指定index位置的元素为ele,并返回此元素
        list.set(1, "CC");//和上面remove一样,并返回此元素
        System.out.println(list);//[456, CC, Person{name='Tom', age=12}, 456]

        //方法八:List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合;(左闭右开区间)

        List list1 = list.subList(2, 4);
        List list2 = list.subList(1, 3);
        System.out.println(list1);
        System.out.println(list2);


    }

    @Test
    public void test1(){
        ArrayList list=new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add(new Person("Tom",12));
        list.add(456);

        System.out.println(list);//[123, 456, AA, Person{name='Tom', age=12}, 456] ;调用了内部重写的toString方法

        //方法1:void add(int index, Object ele):在index位置插入ele元素
        list.add(1,789);//一个一个往后移。789插入到1的位置
        System.out.println(list);//[123, 789, 456, AA, Person{name='Tom', age=12}, 456]

        //方法2:boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
        List list1 = Arrays.asList(1, 2, 3);
        boolean  b = list.addAll(list1);//没有指定索引位置的话默认在最后面添加
        System.out.println(b);//true
        //list.add(list1);//这个也不报错,但是这个是把上面的1,2,3 当成一个元素来进行添加了
        System.out.println(list.size());//9
        System.out.println(list);//[123, 789, 456, AA, Person{name='Tom', age=12}, 456, 1, 2, 3]

        //方法三:Object get(int index):获取指定index位置的元素
        System.out.println(list.get(0));//123


    }






}

3.4Person

package com.atgugui.java;

import java.util.Objects;

/**
 * @author WZ
 * @create 2021-06-20 17:48
 */
public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        System.out.println("Person equals()...");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {

        return Objects.hash(name, age);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值