2021.1 java集合框架1

JAVA集合框架1

一.集合的概念

1.集合的概念

对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能

2.集合与数组的区别

  • 数组长度固定,集合长度不固定
  • 数组可以存储基本类型和引用类型,集合只能存储引用类型
  • 位置位于java.util.*;

二.Collection接口

Collection体系结构

  • 实现类

    ArrayList数组

    LinkedList链表

    SortedSet排序

1. Collection父接口的特点

  • 特点:代表一组类型的对象,一些collection允许有重复的元素(List),而另一些不允许(Set)。一些collection是有序的(List),一些collection是无序的(Set)。

2.Collection接口的使用(方法)----处理元素

/*
Collection接口的使用---处理元素
1.添加元素
2.删除元素
3.遍历元素(重点)
4.判断
*/
public class A {
    public static void main(String[] args) {
//创建集合,接口不能实例化,但是能创建对象;需要利用实现类
        Collection collection=new ArrayList();
//1.添加元素
        collection.add("aaa");//添加字符串
        collection.add("bbb");
     collection.add("ccc");
        collection.add(123);//添加数据
        System.out.println("元素个数:"+collection.size());//集合长度(个数)
        System.out.println(collection.toString());
        System.out.println("=================================");
//2.删除元素
        collection.remove("aaa");//删除一个元素
        System.out.println("元素个数:"+collection.size());//集合长度(个数)
        System.out.println(collection.toString());
//collection.clear();//清空元素
//System.out.println("元素个数:"+collection.size());//集合长度(个数)
//System.out.println(collection.toString());
        System.out.println("=================================");
//3.遍历元素(重点)
                 //(1)使用增强for循环,collection集合没有显示下标,无法使用普通for来遍历
        System.out.println("使用增强for循环遍历集合");
        for (Object object:collection){
            System.out.println(object.toString());
        }
        System.out.println("=================================");
                 //(2)使用迭代器遍历,迭代器是个接口,方法如下
                 //hasNext();判断有没有下一个元素
                 //next();获取下一个元素
                 //remove();删除当前元素
        System.out.println("使用迭代器遍历集合");
         Iterator it=collection.iterator();//这是一个接口
         while(it.hasNext()){
             Object o=it.next();
             System.out.println(o.toString());
             //在迭代过程中不能使用collection的删除方法:collection.remove();
             //迭代里面有自己的删除方法
             //it.remove();
         }
        System.out.println("元素个数:"+collection.size());
        System.out.println("=================================");
//4.判断
        System.out.println(collection.contains("bbb"));//存不存在这个元素
        System.out.println(collection.isEmpty());//是不是空
    }
}
/*结果:
元素个数:4
[aaa, bbb, ccc, 123]
=================================
元素个数:3
[bbb, ccc, 123]
=================================
使用增强for循环遍历集合
bbb
ccc
123
=================================
使用迭代器遍历集合
bbb
ccc
123
元素个数:3
=================================
true
false
*/

3. Collection接口的使用(方法)----处理信息(已有类的信息)

/*
Collection接口的使用---处理已有类的信息
此处处理学生类的信息
*/
public class B {
    public static void main(String[] args) {
        //创建集合,不接口能实例化,但是能创建对象;需要利用实现类
        //1.处理信息
        Collection collection=new ArrayList();
        Student s1=new Student();
        s1.setAge(10);
        s1.setName("aaa");
        Student s2=new Student();
        s1.setAge(11);
        s1.setName("bbb");
        Student s3=new Student();
        s1.setAge(12);
        s1.setName("ccc");
        //1.添加信息
        collection.add(s1);
        collection.add(s2);
        collection.add(s3);
        System.out.println("元素个数"+collection.size());
        System.out.println(collection.toString());
        System.out.println("===================");
        //2.删除信息
        collection.remove(s1);
        System.out.println("删除之后元素个数:"+collection.size());
        System.out.println(collection.toString());
        //collection.clear();全部清除
        //清除只是集合里面清除,对象本身不会清除,添加信息时只是传地址进集合
        System.out.println("===================");
        //3.遍历信息
             //(1)增强for循环遍历
        System.out.println("使用增强for循环遍历集合");
        for (Object object:collection){
            System.out.println(object.toString());
        }
        System.out.println("=================================");
        //(2)使用迭代器遍历,迭代器是个接口,方法如下
        //hasNext();判断有没有下一个元素
        //next();获取下一个元素
        //remove();删除当前元素
        System.out.println("使用迭代器遍历集合");
        Iterator it=collection.iterator();//这是一个接口
        while(it.hasNext()){
            Object o=it.next();
            System.out.println(o.toString());
            //在迭代过程中不能使用collection的删除方法:collection.remove();
            //迭代里面有自己的删除方法
            //it.remove();
        }
        System.out.println("元素个数:"+collection.size());
        System.out.println("=================================");
        //4.判断
        System.out.println(collection.contains(s2));//存不存在这个信息
        System.out.println(collection.isEmpty());//是不是空
    }
}
/*结果:
元素个数3
[aaa 10, bbb 11, ccc 12]
===================
删除之后元素个数:2
[bbb 11, ccc 12]
===================
使用增强for循环遍历集合
bbb 11
ccc 12
=================================
使用迭代器遍历集合
bbb 11
ccc 12
元素个数:2
=================================
true
false
*/
//学生类
public class Student{
    //封装属性
    private int age;
    private String name;
    //构造器,new之后,程序先运行构造器再生成对象
    public Student(){

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

    //可以通过快捷键Alt+Insert:重写常用的方法
    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public int hashCode() {
        int n1=this.name.hashCode();
        int n2=this.age;
        return n1+n2;
    }

    @Override
    public boolean equals(Object obj) {
//        1.判断这两个对象是不是同一个引用
        if(this==obj){
            return true;
        }
//        2.判断obj是否为null
        if(obj==null){
            return false;
        }
//        3.判断两个对象是否为同一类型
        if(obj instanceof Student)//左边为对象,右边为类;
        //obj所指的实际类型是Student的子类型,则true
        {
//            4.强制转换
            Student student=(Student) obj;
//            5.
            if(this.name==student.name&&this.age==student.age)
                return true;
        }
        return false;
    }

    @Override
    public String toString() {
        return "name:"+name+" "+"age:"+age;
    }
}

三.List接口与实现类

1.List接口的概念

  • 为collection接口的子接口

  • 特点:有序、有下标、元素可以重复

    注意:有序的意思是添加的顺序与遍历或者获取的顺序是一致的

  • List因为有序,可以利用下标来访问,而Collection不行,它没有下标

  • List方法除了包含Collection的方法外,还有自己的方法

2.List接口的使用

//List接口的使用
public class C {
    public static void main(String[] args) {
//创建集合,接口不能实例化,但是能创建对象;需要利用实现类
        List list=new ArrayList();
//1.添加元素(可以添加下标)
        list.add(520);//添加数据
        list.add("aaa");//添加字符串
        list.add(0,"111");
        list.add("bbb");
        list.add(0,"000");
        System.out.println("元素个数:"+list.size());//集合长度(个数)
        System.out.println(list.toString());
        System.out.println("====================================");
//2.删除元素
        list.remove(3);//利用角标删除
        list.remove("111");
        System.out.println("删除之后,元素个数:"+list.size());//集合长度(个数)
        System.out.println(list.toString());
        //list.clear();全部清除
        System.out.println("====================================");
//3.遍历元素
                //(1)使用for来遍历
        System.out.println("使用for来遍历");
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
                //(2)使用增强for来遍历
        System.out.println("使用增强for来遍历");
        for (Object object:list){
            System.out.println(object.toString());
        }
               //(3)使用迭代器Iterator遍历,迭代器是个接口,方法如下
                          //hasNext();判断有没有下一个元素
                          //next();获取下一个元素
                         //remove();删除当前元素
        System.out.println("使用迭代器Iterator来遍历");
        Iterator it=list.iterator();
        while(it.hasNext()){
            Object o=it.next();
            System.out.println(o.toString());
            //在迭代过程中不能使用collection的删除方法:collection.remove();
            //迭代里面有自己的删除方法
            //it.remove();
        }
                //(4)使用列表迭代器ListIterator遍历,列表迭代器是个接口
              //列表迭代器与迭代器的区别:
              // 多了许多方法
              // 可以向前或者向后遍历
              // 可以在遍历的时候添加、删除、修改元素
        System.out.println("使用列表迭代器ListIterator来遍历:从前往后遍历");
        ListIterator lit=list.listIterator();
        while(lit.hasNext()){
            System.out.println(lit.nextIndex()+":"+lit.next());
        }
        System.out.println("使用列表迭代器ListIterator来遍历:从后往前遍历");
        //此时指针,经过上面从前往后遍历,已到最后一个,故不用修改指针
        while(lit.hasPrevious()){
            System.out.println(lit.previousIndex()+":"+lit.previous());
        }
        System.out.println("====================================");
//4.判断元素是否存在
        System.out.println(list.contains("000"));
        System.out.println(list.isEmpty());
//5.获取位置
        System.out.println(list.indexOf("000"));
    }
}
/*结果:
元素个数:5
[000, 111, 520, aaa, bbb]
====================================
删除之后,元素个数:3
[000, 520, bbb]
====================================
使用for来遍历
000
520
bbb
使用增强for来遍历
000
520
bbb
使用迭代器Iterator来遍历
000
520
bbb
使用列表迭代器ListIterator来遍历:从前往后遍历
0:000
1:520
2:bbb
使用列表迭代器ListIterator来遍历:从后往前遍历
2:bbb
1:520
0:000
====================================
true
false
0
*/

3.List接口的补充

  • 注意1:集合是没办法存储基本类型的,当你添加一个基本类型进集合时,如底下:list.add(520),其实系统已经帮你自动装箱,变成了包装类
  • 注意2:当你要删除集合里面520这个数据时,利用list.remove(520)是不行的,因为remove(index),删除的是下标的数据。需要将他转为list.remove((Object)520);或者list.remove((Integer)520);或者list.remove(new Integer(520));
//List接口的补充
public class D {
        public static void main(String[] args) {
            //创建集合,接口不能实例化,但是能创建对象;需要利用实现类
            List list=new ArrayList();
//1.添加数据(可以添加下标)
            list.add(520);//添加数据
            list.add(101);//添加数据
            list.add(102);//添加数据
            list.add(103);//添加数据
            list.add(104);//添加数据
            list.add(105);//添加数据
            list.add(106);//添加数据
            list.add(1,100);//添加数据
            System.out.println("元素个数:"+list.size());//集合长度(个数)
            System.out.println(list.toString());
//2.删除数据
            list.remove(3);
            list.remove((Object)520);
            list.remove((Integer)100);
            //list.remove(new Integer(100));
            System.out.println("删除之后元素个数:"+list.size());//集合长度(个数)
            System.out.println(list.toString());
//3.subList(a,b)方法,返回子集合,截取的位置为集合的[a,b)位置
            System.out.println("子集合元素个数:"+list.subList(1,4).size());//集合长度(个数)
            System.out.println(list.subList(1,4));
    }
}
/*结果:
元素个数:8
[520, 100, 101, 102, 103, 104, 105, 106]
删除之后元素个数:5
[101, 103, 104, 105, 106]
子集合元素个数:3
[103, 104, 105]
*/

4.List接口的实现类

  • ArrayList(重点):数组结构实现,查询遍历、增删,运行效率,线程不安全
  • Vector:数组结构实现,查询遍历、增删 ,运行效率,线程安全
  • LinkedList:链表结构实现,增删,查询遍历
    1. ArrayList的用法
//AllayList是List接口的实现类
public class E {
    public static void main(String[] args) {
//创建集合
        ArrayList arrayList=new ArrayList();
//1.添加元素
        //在Student类中进行有参构造
        Student s1=new Student("aaa",5);
        Student s2=new Student("bbb",10);
        Student s3=new Student("ccc",15);
        Student s4=new Student("ddd",20);
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        arrayList.add(s4);
        System.out.println("元素个数:"+arrayList.size());//集合长度(个数)
        System.out.println(arrayList.toString());//此处的toString方法需要重写
        System.out.println("===================================");
//2.删除元素
        //删除元素需要用到equals()方法先进行比较
        //不重写equals()方法,没法删除下面(元素相同,对象不同)的集合元素
        arrayList.remove(new Student("aaa",5));
        System.out.println("元素个数:"+arrayList.size());//集合长度(个数)
        System.out.println(arrayList.toString());
        System.out.println("====================================");
//3.遍历元素
         //(1)使用for循环遍历
         //(2)使用增强for循环遍历
         //(3)使用迭代器遍历
        System.out.println("使用迭代器Iterator来遍历");
        Iterator it=arrayList.iterator();
        while(it.hasNext()){
            Object o=it.next();
            System.out.println(o.toString());
        }
         //(4)使用列表迭代器遍历
        System.out.println("使用列表迭代器ListIterator来遍历:从前往后遍历");
        ListIterator lit=arrayList.listIterator();
        while(lit.hasNext()){
            System.out.println(lit.nextIndex()+":"+lit.next());
        }
        System.out.println("使用列表迭代器ListIterator来遍历:从后往前遍历");
        //此时指针,经过上面从前往后遍历,已到最后一个,故不用修改指针
        while(lit.hasPrevious()){
            System.out.println(lit.previousIndex()+":"+lit.previous());
        }
        System.out.println("====================================");
 //4.判断元素是否存在
        //也需要用到equals()方法,此处方法已被重写
        System.out.println(arrayList.contains(s2));
        System.out.println(arrayList.contains(new Student("ccc",15)));
        System.out.println(arrayList.isEmpty());
        System.out.println("====================================");
 //5.获取位置
        //也需要用到equals()方法,此处方法已被重写
        System.out.println(arrayList.indexOf(s2));
        System.out.println(arrayList.indexOf(new Student("ccc",15)));
    }
}
/*结果:
元素个数:4
[name:aaa age:5, name:bbb age:10, name:ccc age:15, name:ddd age:20]
===================================
元素个数:3
[name:bbb age:10, name:ccc age:15, name:ddd age:20]
====================================
使用迭代器Iterator来遍历
name:bbb age:10
name:ccc age:15
name:ddd age:20
使用列表迭代器ListIterator来遍历:从前往后遍历
0:name:bbb age:10
1:name:ccc age:15
2:name:ddd age:20
使用列表迭代器ListIterator来遍历:从后往前遍历
2:name:ddd age:20
1:name:ccc age:15
0:name:bbb age:10
====================================
true
true
false
====================================
0
1
*/

public class Student{
    //封装属性
    private int age;
    private String name;
    //构造器,new之后,程序先运行构造器再生成对象
    public Student(){

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

    //可以通过快捷键Alt+Insert:重写常用的方法
    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public int hashCode() {
        int n1=this.name.hashCode();
        int n2=this.age;
        return n1+n2;
    }

    @Override
    public boolean equals(Object obj) {
//        1.判断这两个对象是不是同一个引用
        if(this==obj){
            return true;
        }
//        2.判断obj是否为null
        if(obj==null){
            return false;
        }
//        3.判断两个对象是否为同一类型
        if(obj instanceof Student)//左边为对象,右边为类;
        //obj所指的实际类型是Student的子类型,则true
        {
//            4.强制转换
            Student student=(Student) obj;
//            5.
            if(this.name==student.name&&this.age==student.age)
                return true;
        }
        return false;
    }

    @Override
    public String toString() {
        return "name:"+name+" "+"age:"+age;
    }
}
  1. ArrayList类的源码分析

    • 默认容量DEFAULT_CAPACITY=10

    • 存放元素的数组elementDate

    • 实际元素的个数size<=容量

    • ArrayList的无参构造

    注意:new一个ArrayList对象,在没有向集合中添加元素之前,容量为0,实际元素个数为0

 public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    • 在使用add()方法添加一个元素后,容量变为10
    • 每次扩容的大小为原来的1.5倍
 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
  1. Vector类(向量类)

    • 可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。有下标

    • 存储结构:数组

    • Vector类用的很少,使用方法和上面的ArrayList类类似,它的方法也差不多

    • 在遍历上面除了前面说的四种方式
      ​ (1)使用for循环遍历
      ​ (2)使用增强for循环遍历
      ​ (3)使用迭代器遍历
      ​ (4)使用列表迭代器遍历

      还有 (5)使用枚举器elements(),它的返回值类型是**Enumeration **,使用方法和迭代器也类似

  2. LinkedList类

    • 存储结构:双项链表-----有从头指到尾,也有从尾指到头
    • 使用方法
//LinkedList是List接口的实现类
//LinkedList的使用
public class F {
    public static void main(String[] args) {
//创建集合
        LinkedList linkedList = new LinkedList();
//1.添加元素
        //在Student类中进行有参构造
        Student s1=new Student("aaa",5);
        Student s2=new Student("bbb",10);
        Student s3=new Student("ccc",15);
        Student s4=new Student("ddd",20);
        Student s5=new Student("eee",25);
        linkedList.add(s1);
        linkedList.add(s2);
        linkedList.add(s3);
        linkedList.add(s4);
        linkedList.add(s5);
        System.out.println("元素个数:"+linkedList.size());//集合长度(个数)
        System.out.println(linkedList.toString());//此处的toString方法需要重写
        System.out.println("===================================");
//2.删除元素
        //删除元素需要用到equals()方法先进行比较
        //不重写equals()方法,没法删除下面(元素相同,对象名不同)的集合元素
        linkedList.remove(new Student("aaa",5));
        linkedList.remove(1);
        System.out.println("元素个数:"+linkedList.size());//集合长度(个数)
        System.out.println(linkedList.toString());
        System.out.println("====================================");
//3.遍历元素
        //(1)使用for来遍历
        System.out.println("使用for来遍历");
        for(int i=0;i<linkedList.size();i++){
            System.out.println(linkedList.get(i));
        }
        //(2)使用增强for来遍历
        System.out.println("使用增强for来遍历");
        for (Object object:linkedList){
            System.out.println(object.toString());
        }
        //(3)使用迭代器遍历
        System.out.println("使用迭代器Iterator来遍历");
        Iterator it=linkedList.iterator();
        while(it.hasNext()){
            Object o=it.next();
            System.out.println(o.toString());
        }
        //(4)使用列表迭代器遍历
        System.out.println("使用列表迭代器ListIterator来遍历:从前往后遍历");
        ListIterator lit=linkedList.listIterator();
        while(lit.hasNext()){
            System.out.println(lit.nextIndex()+":"+lit.next());
        }
        System.out.println("使用列表迭代器ListIterator来遍历:从后往前遍历");
        //此时指针,经过上面从前往后遍历,已到最后一个,故不用修改指针
        while(lit.hasPrevious()){
            System.out.println(lit.previousIndex()+":"+lit.previous());
        }
        System.out.println("====================================");
        //4.判断元素是否存在
        //也需要用到equals()方法,此处方法已被重写
        System.out.println(linkedList.contains(s2));
        System.out.println(linkedList.contains(new Student("ccc",15)));
        System.out.println(linkedList.isEmpty());
        System.out.println("====================================");
        //5.获取位置
        //也需要用到equals()方法,此处方法已被重写
        System.out.println(linkedList.indexOf(s2));
        System.out.println(linkedList.indexOf("name:ddd age:20"));//这样子找不到需要找的字符串位置
        System.out.println(linkedList.indexOf(new Student("eee",25)));
    }
}
/*结果:
元素个数:5
[name:aaa age:5, name:bbb age:10, name:ccc age:15, name:ddd age:20, name:eee age:25]
===================================
元素个数:3
[name:bbb age:10, name:ddd age:20, name:eee age:25]
====================================
使用for来遍历
name:bbb age:10
name:ddd age:20
name:eee age:25
使用增强for来遍历
name:bbb age:10
name:ddd age:20
name:eee age:25
使用迭代器Iterator来遍历
name:bbb age:10
name:ddd age:20
name:eee age:25
使用列表迭代器ListIterator来遍历:从前往后遍历
0:name:bbb age:10
1:name:ddd age:20
2:name:eee age:25
使用列表迭代器ListIterator来遍历:从后往前遍历
2:name:eee age:25
1:name:ddd age:20
0:name:bbb age:10
====================================
true
false
false
====================================
0
-1
2
*/

所用的Student类同上

  1. LinkedList类的源码分析
    • int size:集合大小,默认为0
    • Node first:链表的头节点,默认为null
    • Node last:链表的尾节点,默认为null
public boolean add(E e) {
        linkLast(e);
        return true;
    }

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++;
    }

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;
    }
    
}
  1. ArrayList和LinkedList区别

    ArrayList和LinkedList区别

链表:增删快是因为,可以直接改变指针指向,如可以让B.next---->D,D.previous----->B从而达到删除C的效果

​ 查询慢是因为,链表开辟的空间不是连续的,不能像数组一样定位,只能通过指针指到需要的数据

posted @ 2021-01-29 16:28  维他命D片  阅读(46)  评论(0编辑  收藏  举报