Java第十二课 集合

目录

一、从“痛点切入”,我们为什么需要集合

二、集合的核心概念

1.集合框架的“家谱”

2.与数组的核心区别

3.集合的基本用法

三、详解:从接口到实现

1.Collection接口通用方法

2.自建类Student

练习一:补全代码

3.三种遍历

四、习题答案

五、答疑解惑


注意

这篇文章适合初学集合的新手,主要讲的是集合的基本用法,依托于Collection。

一、从“痛点切入”,我们为什么需要集合

开篇案例对比:

// 用数组存储3个学生信息,再新增1个学生
Student[] students = new Student[3];
students[0] = new Student("张三", 18);
students[1] = new Student("李四", 19);
students[2] = new Student("王五", 20);
// 想新增第4个学生?必须创建新数组,复制旧数据
Student[] newStudents = new Student[4];
System.arraycopy(students, 0, newStudents, 0, 3);
newStudents[3] = new Student("赵六", 21);

大家看完这段代码,相信已经发现了我们以往所用的引用数据类型的痛点。

------------------数组长度固定,使用不方便--------------

---------存放数据成员类型固定,不灵活-----------------

---------内存空间连续,内存利用率不高-----------------

-----------------插入删除元素效率低------------------------

所以,我们的java提供了一种“容器”来解决这种问题

                                                                                                -----集合

它能自动扩容、提供丰富的操作方法,还能根据需求选择不同的数据结构。

二、集合的核心概念

1.集合框架的“家谱”

 这节课,我们主要学的,也就是单列集合:根接口(Collection)这条线。

// 根接口:Collection 子接口:List 实现类:ArrayList

//创建对象时,一般要指定泛型。

//前面指定泛型,后面可以省略

//Collection<String> collection=new ArrayList<String>();

Collection collection=new ArrayList<>();

2.与数组的核心区别

特性数组集合
长度固定(声明时确定)动态可变(自动扩容)
存储类型基本类型 / 引用类型仅能存引用类型(基本类型会自动装箱)
元素重复性允许重复List 允许,Set 不允许
操作方法仅 length 属性 + Object 方法丰富(add/remove/contains 等)

3.集合的基本用法

public class Test {
    public static void main(String[] args) {
        // 常见关系:
        // 根接口:Collection 子接口:List 实现类:ArrayList
        //创建对象时,一般要指定泛型。
        //前面指定泛型,后面可以省略
        //Collection<String> collection=new ArrayList<String>();
        Collection collection=new ArrayList<>();
        //使用集合
        if(collection.isEmpty()){
            System.out.println("collenction为空");
        }
        System.out.println("长度:"+collection.size());
        collection.add("hello");
        //思考:不是只能存引用数据类型吗?为什么可以放1和a?
        collection.add(1);
        int a=1;
        collection.add(a);
        Integer integer=1;
        collection.add(integer);
        collection.add('a');
        int[] arr={1,2,3};
        collection.add(arr);
    }
}

细心的小伙伴已经发现在与数组的核心区别中,我在存储类型后面写了个自动装箱。

Collection<Integer> coll = new ArrayList<>();
coll.add(10); // 自动装箱:int→Integer(引用类型)
coll.add(20);
System.out.println( coll.size()); // 输出2(长度),体现动态扩容

三、详解:从接口到实现

1.Collection接口通用方法

以生活容器场景类比:

add(E e):往容器里放东西;
remove(Object o):从容器里拿出某个东西;
contains(Object o):检查容器里有没有某个东西;
size():看看容器里有多少东西;
isEmpty():检查容器是不是空的;
addAll(Collection c):把另一个容器里的东西全倒进来

具体实战:

public class Test02 {
    public static void main(String[] args) {
        Collection<String> collection=new ArrayList<>();
        //常用方法测试-----------------------
        collection.add("hello");
        //boolean contains(Object var1);//判断是否包含
        boolean flag1=collection.contains("hello");
        System.out.println(flag1);
        //----------------------------------------------------
        Collection collection2=new ArrayList<>();
        //addAll
        collection.addAll(collection2);
        //boolean containsAll(Collection<?> var2);
        boolean flag2=collection.addAll(collection2);

        //----------------------------------------------------------
        //toArray();
        Object[] obj=collection.toArray();
        System.out.println(obj);
        System.out.println(Arrays.toString(obj));
        //remove 移除
        collection.remove("!");//------无返回
        boolean flag3=collection.remove("1");//-----有返回,只判断,不删除

        boolean flag4=collection.removeAll(collection2);

        //clear();
        collection.clear();

        //equals
        boolean flag5=collection.equals(collection2);

        //hashCode()
        //为什么集合的hashCode有的是正数有的是负数?
        System.out.println(collection.hashCode());
        System.out.println(collection2.hashCode());

        }
    }

2.自建类Student

那如果,我们创建了一个类(Student),我们的Collection该如何派上用场呢?

public class Student {
    private String name;
    private int age;
    private String sex;
    
    public Student() {
    }
    public Student(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
//set...get....
//toString必须重写
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]";
    }
    
    
}

将刚刚的方法利用在Student的测试类上,你会不会使用呢?

练习一:补全代码

尝试用上面所学的Collection中的方法补全代码

public class Test {

    public static void main(String[] args) {

        Collection<Student> collection=new ArrayList<>();

        Student student=new Student("李01",18,"男");

//如:add

//.........

    }

}

3.三种遍历

(1)普通for循环://遍历1--for+toArray

      Object[] arr=collection.toArray();

      for(int i=0;i<arr.length;i++){

          System.out.println(arr[i]);

      }

(2)迭代器(Iterator):

      Iterator<String> iterator= collection.iterator();//获取迭代器对象

      while (iterator.hasNext()) {

          String string=iterator.next();

          System.out.println(string);

      }

(3)增强for循环:

      for(Object obj:collection.toArray()){

          System.out.println(obj);

      }

在选择三种遍历方式的时候,要考虑我们的实际需求。

只读-------加强for循环

修改-------普通for循环

删除-------迭代器

四、习题答案

public class Test {
    public static void main(String[] args) {
        Collection<Student> collection=new ArrayList<>();
        Student student=new Student("李霄01",18,"男");
        //add
        collection.add(student);
        Collection<Student> collection2=new ArrayList<>();
        Student student2=new Student("李霄02",18,"女");
        collection2.add(student2);
        System.out.println(collection.size());
        //addAll
        collection.addAll(collection2);

        System.out.println(collection);
        System.out.println(collection2);

        //contains
        boolean flag1=collection.contains("李霄");
        boolean flag2=collection.containsAll(collection2);

        System.out.println(flag1);
        System.out.println(flag2);

        //toArray;
        Object[] obj1= collection.toArray();
        Object[] obj2= collection2.toArray();
        


        //remove
        collection.remove("18");
        boolean flag3= collection2.remove("18");

        System.out.println(collection);
        System.out.println(flag3);
        System.out.println(collection2);

    }
}

五、答疑解惑

1.集合为什么不能存储基本数据类型?

因为集合设计初衷是操作对象(引用类型),基本类型会通过自动装箱(如int→Integer)转为包装类(引用类型)存入。

2.为什么hashCode有时候是正数有时候是负数?

Java 中hashCode()的返回值是int类型,而int的取值范围是 -2³¹ ~ 2³¹-1(即 - 2147483648 ~ 2147483647)。

3.equals和hashCode的关系?

两个对象equals为 true,则hashCode必须相等;
hashCode相等,equals不一定为 true(哈希冲突)。

4.ArrayList扩容机制?

初始容量 10,满了之后扩容为原来的 1.5 倍(旧容量 + 旧容量 >>1),通过数组复制实现。

知其然

        更知其所以然

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值