集合框架笔记

目录

一.集合

1.集合的概念:

2.为啥使用集合:

3.集合和数组的异同:

4.集合体系的框架结构:

二.Collection接口:

1.常用方法:

(1).增加:

(2)删除:

(3)遍历:

(3.1)可以通过toArray将集合转换成数组进行遍历

(3.2)迭代器:Iterator iterator(),返回此集合中的元素的迭代器。

(3.3)增强for循环(foreach):

(4)判断:

(5)其他:

三.List接口

List特有的方法有如下:

ListIterator遍历(此接口继承Iterator)

1. ArrayList

四.Set接口

1.HashSet

2.TreeSet

五.Map接口 

1.HashMap

2.TreeMap


一.集合

1.集合的概念:

Java API中所提供的一系列类的实例,可以用来动态地存放多个对象。java集合框架提供了一套性能优良,使用方便的接口和类,位于java.util包中。

2.为啥使用集合:

当我们要存储多个数据,并且这个数据还会不断更新、改变的时候,数组的特性就难以支撑,所以需要使用集合。

3.集合和数组的异同:

数组的长度固定,集合不固定,可随意对其进行增删改查。

数组存储的数据单一,集合可存储多种类型的数据。

数组可存储引用类型和基本类型,集合只能存储引用类型,若要存储基本类型需得将其装箱为对应的包装类。

4.集合体系的框架结构:

二.Collection接口:

Collection是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
JDK 不提供此接口的任何直接实现.它提供更具体的子接口(如Set和List)实现

因为接口无法实例化,所以我们需要使用实现类进行创建对象(多态),此处用ArrayList实现类。

例如:

1.常用方法:

(1).增加:

add(元素)添加指定的元素、addAll(集合)添加一个完整的集合进入当前集合

(2)删除:

remove(元素)删除指定的元素、removeAll(集合)删除添加的集合、clear()删除集合中的所有元素

(3)遍历:

(3.1)可以通过toArray将集合转换成数组进行遍历

(3.2)迭代器:Iterator<E> iterator(),返回此集合中的元素的迭代器。
    • hasNext()

      返回 true如果遍历正向列表,列表迭代器有多个元素。

      next()

      返回列表中的下一个元素,并且前进光标位置。

(3.3)增强for循环(foreach):

​    for(集合/数组中元素的数据类型 变量名 :  集合/数组名) {

​        // 已经将当前遍历到的元素封装到变量中了,直接使用变量即可

​    }

 

(4)判断:

isEmpty()如果此集合不包含元素,则返回true。

           contains(元素) 如果此集合包含指定元素,返回true

           containsAll(集合)如果此集合包含指定集合的所有元素,则返回true。

(5)其他:

size()返回此集合的元素数

 retainAll:

仅保留此集合中包含在指定集合中的元素。相当于求交集,返回结果为布尔型,如果为false,说明此集合是指定集合的一部分,此集合前后并未改变,为true说明此集合发生了改变,删除了指定集合中不包含的元素,仅保留了指定集合包含的部分。

三.List接口

由集合框架结构图可知,List接口继承Collection接口,所以Collection里包含的常用方法List也有,不同的是List有序,可以根据下标来增删改查、遍历(get(索引))。List有如下特点:

  • 存取有序

  • 可以重复

  • 有索引

List特有的方法有如下:

方法名描述
void add(int index,E element)在此集合中的指定位置插入指定的元素
E remove(int index)删除指定索引处的元素,返回被删除的元素
E set(int index,E element)修改指定索引处的元素,返回被修改的元素
E get(int index)返回指定索引处的元素

  

ListIterator遍历(此接口继承Iterator)

  • 允许程序员沿任一方向遍历列表的列表的迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置

    • hasPrevious()

      返回 true如果遍历反向列表,列表迭代器有多个元素。

      previous()

      返回列表中的上一个元素,并向后移动光标位置。

      previousIndex()

      返回由后续调用 previous()返回的元素的索引。

    • 由上图可知,如果要进行逆序遍历,必须使得遍历起始位置位于集合最后一个元素的后面,不然在集合的第一个元素的前面,没有上一个元素,无法遍历。

1. ArrayList

ArrayList集合

  • 可调整大小的数组的实现List接口。 实现所有可选列表操作,并允许所有元素,包括null 。

​    底层是数组结构实现,查询快、增删慢

可通过构造方法创建ArrayList对象。

由于ArrayList实现List接口,所以List有的方法ArrayList也具备,所以ArrayList的常用方法参考List就行。下面通过一个例子来使用一下ArrayList

import java.util.ArrayList;//导包系统能自动完成
import java.util.Iterator;
import java.util.Scanner;
//通过ArrayList建一个Person类(自建的Person类)的集合,并对集合进行去重和遍历的操作
public class ArrayListExer {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        ArrayList<Person> persons = new ArrayList<>();//通过构造函数来创建一个空的ArrayList集合
        System.out.println("请输入您要录入的次数:");
        int count = sc.nextInt();
        int n = 0;
        while (true) {//通过无限循环录入信息
            System.out.println("请输入姓名:");
            String name = sc.next();
            System.out.println("请输入年龄:");
            int age = sc.nextInt();
            Person per = new Person(name, age);//将录入的信息传入Person对象
            persons.add(per);//将Person对象添加到persons集合里
            n++;//通过n来控制循环次数
            if (n >= count) { //若n=限定的录入次数count则打破循环
                break;
            }
        }
        System.out.println(persons);
        //通过迭代器和增强for循环遍历集合
        Iterator<Person> iter = persons.iterator();//通过Iterator遍历器对persons集合进行遍历
        for(Object o:persons){//通过foreach增强for循环对persons进行遍历
            if(iter.hasNext()){//判断当前位置是否有下一个元素
                Person next = iter.next();//获取下一个元素
                System.out.println(next);//打印获取的下一个元素
            }
        }
        //删除集合中重复的元素
        for(int i=0;i<persons.size()-1;i++){
            for(int j=i+1;j<persons.size();j++){
                Person person1 =  persons.get(i);//获取persons的第i个元素
                Person person2 =  persons.get(j);
                if(person1.getName().equals(person2.getName())&&person1.getAge().equals(person2.getAge())){
                    persons.remove(j);//判断第i个元素是否和第j个元素相等(姓名、年龄),相等则删除第j个元素
                   //假设有三个连续相同的元素,删除第二个后,后续的元素会往前移,而i元素会继续和j+1元素相比,
                    // 但此时j+1为原先的j+2,所以不会删除第三个重复的元素,所以删除一个元素后,我们要将j减1
                    j--;
                }
            }
        }
        System.out.println(persons);
    }
}

LinkedList集合

  • 双链表实现了ListDeque接口。 实现所有可选列表操作,并允许所有元素(包括null )。

    所有的操作都能像双向列表一样预期。

​    底层是链表结构实现,查询慢、增删快,线程不安全,但效率高。

方法名说明
public void addFirst(E e)在该列表开头插入指定的元素
public void addLast(E e)将指定的元素追加到此列表的末尾
public E getFirst()返回此列表中的第一个元素
public E getLast()返回此列表中的最后一个元素
public E removeFirst()从此列表中删除并返回第一个元素
public E removeLast()从此列表中删除并返回最后一个元素

四.Set接口

  • 不可以存储重复元素

  • 没有索引(无序),不能使用普通for循环遍历

  • 由于Set接口继承Collection,所以Collection有的方法set也具备,参考Set接口即可。

1.HashSet

  • 此类实现Set接口,由哈希表(实际为HashMap实例)支持。 对集合的迭代次序不作任何保证(无序);允许null值。

  • 不可以存储重复元素

  • 没有索引,不能使用普通for循环遍历

散列表:查询、修改、添加、删除的效率都比较高(可以存储重复元素)。

散列表的逻辑:对元素进行取余(除数组长度,取余)操作,将余数作为元素的索引,存入相应的数组位置(如下图所示)。散列表相当于数组和链表的结合,所以存取、增删改查效率都比较高

HashSet底层是散列表,本质通过以下两个方法实现,但是不能存储重复元素。

int HashCode();确定散列表的下标

 boolean equals(Object o);判断同一个下标对应的链表中的数据是否相等

HashSet的基本应用

由遍历结果可知,HashSet的存取不是一一对应的,所以存取无序 。

public class HashSetExer2 {
    public static void main(String[] args) {
        HashSet<Object> hsS = new HashSet<>();
        Student st1 = new Student("李华",20);
        Student st2 = new Student("王芳",19);
        Student st3 = new Student("李华",21);
        Student st4 = new Student("李华",20);
        hsS.add(st1);
        hsS.add(st2);
        hsS.add(st3);
        hsS.add(st4);
        for(Object o:hsS){
            System.out.println(o);
        }
    }
}
class Student {
    private String name;
    private Integer age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

    @Override
    public boolean equals(Object o) {//重写equals对参数进行比较
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (name != null ? !name.equals(student.name) : student.name != null) return false;
        return age != null ? age.equals(student.age) : student.age == null;
    }

    @Override
    public int hashCode() {//重写HashCode
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (age != null ? age.hashCode() : 0);
        return result;
    }
}

//结果为:

Student{name='李华', age=21}
Student{name='李华', age=20}
Student{name='王芳', age=19}
重复的元素未被存储

HashSet集合存储自定义类型元素,要想实现元 素的唯一,要求必须重写hashCode方法和equals方法  

2.TreeSet

  • 不可以存储重复元素,无序

  • 没有索引

  • 不能存储null值

  • 可以将元素按照规则进行排序

    • TreeSet():根据其元素的自然排序进行排序

    • TreeSet(Comparator comparator) :根据指定的比较器进行排序

 两种比较方法的对比

  • 自然排序: 自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序

  • 比较器排序: 创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序

  • 在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,必须使用比较器排序

 //根据自然排序进行排序

public class TreeSetExer {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet();

        for (int i = 0; i < 10; i++) {
            Student student = new Student();
            student.setName("wangfang");
            student.setChinese(Math.random() * (93 - 91) + 91);//通过Math.random来生成随机成绩
            student.setMath(Math.random() * (93 - 91) + 91);
            student.setEnglish(Math.random() * (93 - 91) + 91);
            student.setAge((int) (Math.random() * (20 - 18) + 18));
            treeSet.add(student);
        }
        for(Student o:treeSet) {
            System.out.println(o+"-->"+o.getSum());
        }
    }

}
//由于String类型的数据没有自然顺序,要运用自然排序Comparable,必须在定义的类中重写compareTo()
class Student implements Comparable<Student> {
    private String name;
    private Integer age;
    private Double chinese;
    private Double math;
    private Double english;

    public Student() {
    }

    public Student(String name, Integer age, Double chinese, Double math, Double english) {
        this.name = name;
        this.age = age;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public Double getChinese() {
        return chinese;
    }

    public void setChinese(Double chinese) {
        this.chinese = chinese;
    }

    public Double getMath() {
        return math;
    }

    public void setMath(Double math) {
        this.math = math;
    }

    public Double getEnglish() {
        return english;
    }

    public void setEnglish(Double english) {
        this.english = english;

    }

    public Double getSum() {
        Double sum = chinese + math + english;
        return sum;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", chinese=" + chinese +
                ", math=" + math +
                ", english=" + english +
                '}';
    }

    @Override
    //+ 如果返回值为负数,表示当前存入的元素是较小值,存左边
    //+ 如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
    //+ 如果返回值为正数,表示当前存入的元素是较大值,存右边
    public int compareTo(Student o) {
        int result = (int) (o.getSum() - this.getSum());
        result = (result == 0) ? (int) (o.getChinese() - this.getChinese()) : result;
        result = (result == 0) ? (int) (o.getMath() - this.getMath()) : result;
        result = (result == 0) ? (int) (o.getEnglish() - this.getEnglish()) : result;
        result = (result == 0) ? (o.getName().compareTo(this.getName())) : result;
        return result;
    }
}

五.Map接口 

  • 双列集合,一个键对应一个值

  • 由于key的底层是红黑树

V put(K key,V value);//key(键)唯一,value(值)可以重复

viod putAll(Map<?extends K,? extends V> map);//加入一整个Map集合

V remove(key);//删除key,会返回V

void clear();//清空集合的所有元素

//Map遍历方法1

public class MapDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<String, String>();

        //添加元素
        map.put("001", "李华");
        map.put("002", "王芳");
        map.put("003", "赵素");

        //获取所有键的集合。用keySet()方法实现
        Set<String> keySet = map.keySet();
        //遍历键的集合,获取到每一个键。用增强for实现
        for (String key : keySet) {
            //根据键去找值。用get(Object key)方法实现
            String value = map.get(key);
            System.out.println(key + "," + value);
        }
    }
}

//Map遍历2

public class MapDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<String, String>();

        //添加元素
          map.put("001", "李华");
        map.put("002", "王芳");
        map.put("003", "赵素");

        //获取所有键值对对象的集合
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        //遍历键值对对象的集合,得到每一个键值对对象
        for (Map.Entry<String, String> me : entrySet) {
            //根据键值对对象获取键和值
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key + "," + value);
        }
    }
}

1.HashMap

  • HashMap底层是哈希表结构的

  • 依赖hashCode方法和equals方法保证键的唯一

  • 如果键要存储的是自定义对象,需要重写hashCode和equals方法,下面通过一个例子来展示这条特性。

// 创建一个HashMap集合,键是学生对象(Student),值是居住地 (String)。存储多个元素,并遍历。

public class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    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 boolean equals(Object o) {//在类中重写equals方法,用于比较对象是否重复
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {    //重写hashCode
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
}

//测试类:

public class HashMapDemo {
    public static void main(String[] args) {
        //创建HashMap集合对象
        HashMap<Student, String> hm = new HashMap<Student, String>();

        //创建学生对象
        Student s1 = new Student("李华", 19);
        Student s2 = new Student("赵四", 20);
        Student s3 = new Student("李华", 19);
        Student s4 = new Student("赵四", 18);

        //把学生添加到集合
        hm.put(s1, "西安");
        hm.put(s2, "武汉");
        hm.put(s3, "郑州");
        hm.put(s4, "北京");

        //遍历集合
        Set<Student> keySet = hm.keySet();
        for (Student key : keySet) {
            String value = hm.get(key);
            System.out.println(key.getName() + "," + key.getAge() + "," + value);
        }
    }
}

2.TreeMap

  • TreeMap底层是红黑树结构

  • 依赖自然排序或者比较器排序,对键进行排序

  • 如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则(和之前的TreeSet类似,只不过对集合进行操作时多加一个键)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值