3-Java集合框架详解 通俗易懂

集合的概念:对象的容器,定义了对多个对象进行操作的常用方法,可实现数组的功能
和数组区别:1、数组长度固定,集合长度不固定2,数组可以放基本类型和引用类型,集合只能放引用类型
位置:java.util

Collection体系集合

Collection父接口

package operator;

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

//Collection接口的使用
//1,添加元素
//2,删除元素
//3,遍历元素
//4,判断元素是否存在
public class Demo01 {
    public static void main(String[] args) {
        //创建集合对象
        Collection coll = new ArrayList();//父类引用,Collection接口和子接口list和set都不能实例化,只能用ArrayList实例化
        //添加元素
        coll.add("apple");//其实用的就是ArrayList的add方法,重写了父类Collection的add方法
        coll.add("banana");
        coll.add("orange");
        coll.add("grape");
        System.out.println(coll.size());//4
        System.out.println(coll);//[apple, banana, orange, grape]
        //删除元素
        coll.remove("banana");
        System.out.println(coll.size());//3
        //遍历元素1,增加for
        for (Object obj : coll) {
            System.out.println(obj);
            //apple
            //orange
            //grape
        }
        //遍历元素2,使用迭代器(迭代器专门用来遍历集合的元素)
        //hasNext()方法判断有没有下一个元素
        //next()方法获取下一个元素
        //remove()方法删除当前元素

        Iterator it = coll.iterator();//Collection中的方法iterator(),获取一个 Iterator 对象。Iterator 对象可以用来遍历集合中的元素。Iterator 是一个接口,定义了遍历集合的方法。
        while (it.hasNext()) {
            String s = (String) it.next();
            System.out.println(s);
            //迭代器不能用collections.remove()方法删除元素,只能用迭代器的remove()方法删除元素
            //it.remove();
        }
        //判断元素是否存在
        System.out.println(coll.contains("apple"));//true

    }
}

案例,定义一个学生类

package operator;

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

    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 String toString() {
        return "Student[name="+name+", age="+age+"]";
    }
}
package operator;

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

public class Demo02 {
    //Collection的使用,保存学生信息
    public static void main(String[] args) {
        //创建Collection集合对象
        Collection collection = new ArrayList();
        //1,添加数据
        Student student1 = new Student("张三", 20);
        Student student2 = new Student("王五", 22);
        Student student3 = new Student("李四", 22);
        collection.add(student1);
        collection.add(student2);
        collection.add(student3);
        System.out.println(collection.size());//3
        System.out.println(collection.toString());//[Student[name=张三, age=20], Student[name=王五, age=22], Student[name=李四, age=22]]
        //collection.clear();,删除之后 ,其实三个对象还在,

        //2,遍历集合
        for (Object obj : collection) {
            Student student = (Student) obj;
            System.out.println(student.getName() + " " + student.getAge());
        }
        //迭代器
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()) {
            Student student = (Student) iterator.next();
            System.out.println(student.getName() + " " + student.getAge());
            //张三 20
            //王五 22
            //李四 22
        }
    }
}

List集合-List子接口

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

package operator;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

//List子接口
//特点:有序,有下标,元素可重复,
public class Demo03 {
    public static void main(String[] args) {
        //先创建集合对象
        List list = new ArrayList();
        //添加元素
        list.add("apple");
        list.add("banana");
        list.add(0,"orange");
        System.out.println(list.toString());
        //删除元素
        list.remove(1);
        System.out.println(list.toString());
        //遍历
        //for
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        //增加for
        for (Object obj : list) {
            System.out.println(obj);
            }
        //迭代器
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        //使用列表迭代器,和Iterator的区别,listIterator可以向前或向后遍历,添加,删除,修改元素
        ListIterator list1 = list.listIterator();
        while (list1.hasNext()) {
            System.out.println(list1.nextIndex() + " " + list1.next());//从前往后
        }
            //0 orange
            //1 banana
        while(list1.hasPrevious()){
            System.out.println(list1.previousIndex()+" "+list1.previous());//从后往前
            //1 banana
            //0 orange
        }
        //判断
        System.out.println(list.contains("banana"));//true
        //获取位置
        System.out.println(list.indexOf("banana"));//1


    }
}
package operator;

import java.util.ArrayList;
import java.util.List;

public class Demo04 {
    public static void main(String[] args) {
        List List = new ArrayList();
        List.add(20);//自动装箱
        List.add(30);
        List.add(40);
        List.add(50);
        List.add(60);
        System.out.println(List.size());
        System.out.println(List.toString());//[20, 30, 40, 50, 60]
        //删除操作,两种方法,list.remove(0)
        List.remove(new Integer(20));//数字转成Integer对象
        System.out.println(List.toString());//[30, 40, 50, 60]
        //补充方法sublist,返回子集合,含头不含尾
        List<Integer> subList = List.subList(1, 3);
        System.out.println(subList.toString());//[40, 50]

List实现类

ArrayList的使用

package operator;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;

//ArrayList的使用
//存储结构:数组、查找遍历速度快、增删慢

public class Demo05 {
    public static void main(String[] args){

    ArrayList list = new ArrayList();
    //添加元素
    Student s1=new Student("张三", 20);
    Student s2=new Student("李四", 22);
    Student s3=new Student("王五", 27);
    list.add(s1);
    list.add(s2);
    list.add(s3);
    System.out.println(list.size());
    System.out.println(list.toString());
    //删除元素
        list.remove(s2);
        System.out.println(list.size());//2
        System.out.println(list.toString());//[Student[name=张三, age=20], Student[name=王五, age=27]]
        //遍历元素
        //使用迭代器
        Iterator iterator = list.iterator();
        while(iterator.hasNext()){
            Student s = (Student)iterator.next();
            System.out.println(s.toString());
        }
        //Student[name=张三, age=20]
        //Student[name=王五, age=27]
        //列表迭代器
        ListIterator listIterator = list.listIterator();
        while(listIterator.hasNext()){
                        Student s = (Student)listIterator.next();
                        System.out.println(s.toString());
        }
        //Student[name=张三, age=20]
        //Student[name=王五, age=27]
        while(listIterator.hasPrevious()){
                Student s = (Student)listIterator.previous();
                System.out.println(s.toString());
        }
        //Student[name=王五, age=27]
        //Student[name=张三, age=20]
        //
    }
}

ArrayList源码分析
private static final int DEFAULT_CAPACITY = 10;默认容量大小为10;注意:如果没有向集合中添加任何元素时,容量为0,添加一个元素之后,容量为10,要回到源码去看
每次扩容大小是原来的1。5倍
transient Object[] elementData;存放元素的数组
private int size;实际的元素的个数

Vector-开发用得不是特别多,了解即可

数组结构实现、查询快、增删慢
JDK1。0版本,运行效率慢、线程安全

package operator;

import java.util.Enumeration;
import java.util.Vector;

//Vector
//存储结构:数组
public class Demo01 {
    public static void main(String[] args) {
        Vector vector = new Vector();
        //添加元素
        vector.add("苹果");
        vector.add("芒果");
        vector.add("香蕉");
        System.out.println(vector.size());
        //删除
        //vector.remove(1);
        //vector.remove("苹果");
        //vector.clear();
        //遍历
        //特有的方法,枚举器
        Enumeration en = vector.elements();
        while (en.hasMoreElements()) {
            System.out.println(en.nextElement());
        }
        //其他方法
        System.out.println(vector.firstElement());

    }
}

LinkedList

链表结构实现,增删快,查询慢
package operator;
//LinkList的使用
//存储结构:双向链表


import java.util.Iterator;
import java.util.LinkedList;

public class Demo01 {
    public static void main(String[] args) {
       //创建集合
        LinkedList list = new LinkedList<>();
        //添加元素
        Student s1 = new Student("张三", 20);
        Student s2 = new Student("李四", 20);
        Student s3= new Student("王五", 20);
        list.add(s1);
        list.add(s2);
        list.add(s3);
       System.out.println(list.size());
       //删除
        list.remove(s2);
        System.out.println(list.size());
        //遍历
        for (Object obj : list) {
            Student s = (Student) obj;
            System.out.println(s.getName() + " " + s.getAge());
        }
        //使用迭代器
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Student s = (Student) it.next();
            System.out.println(s.getName() + " " + s.getAge());
        }
    }
}

源码分析

不同结构实现方式

泛型

和之前的类差不多,只是之前的类参数是基本类型,现在是引用类型

泛型类

package operator;
//泛型类
//语法:类名<T>,T取绝你希望是什么引用类型,如果要String,就用String
//T是类型点位符,表示一种引用类型,如果写多个就用逗号隔开
//**如果在new对象时,已经把参数类型定为String,那下面的方法show就不能传入111,会报错,除非在new对象时,没写t的类型,那上面方法show,你传什么类型进去,print就会输出什么类型**
//**所以下面的泛型集合,就是在new的时候,如果已经传入类型,那下面的方法,基本都会限制为你传入的类型**
public class MyGeneric<T> {
    //使用泛型T
    //创建变量
    T t;
    //泛型作为方法的参数
    public void show(T t) {
        System.out.println(t);
    }
    //泛型作为方法的返回值
    public T get(T t) {
        return t;
    }

}

package operator;

public class TestGeneric {
    public static void main(String[] args) {
        //使用泛型类创建对象
        //1、泛型只能使用引用类型 2、不同的泛型类型对象,不能相互赋值
        MyGeneric<String> myGeneric = new MyGeneric();//创建MyGeneric对象,泛型类型为String,String是自己定义的
        myGeneric.t="Hello World";//给MyGeneric对象赋值
        myGeneric.show("大家好");
        String str = myGeneric.get("你好你好");
        System.out.println(str);


        MyGeneric<Integer> myGeneric2 = new MyGeneric<>();//创建MyGeneric对象,泛型类型为Integer
        myGeneric2.t=100;
        myGeneric2.show(200);
        //大家好
        //你好你好
        //200

    }
}

泛型接口

定义接口
package operator;
//泛型接口
//语法:接口名
//注意,不能创建泛型静态常量

public interface MyInterface<T> {
    String name="张三";

    T server(T t);


}

两种写法,已经确定接口类型的

package operator;
//实现接口时就要把类固定了
public class MyInterfaceImpl implements MyInterface<String> {
    @Override
    public String server(String s) {
        System.out.println(s);
        return s;
    }


}

还没确定接口类型

package operator;
//如果不想那么快就定义接口的类型时,实现类也加上类型参数
public class MyInterfaceImpl2<T> implements MyInterface<T> {

    @Override
    public T server(T t) {
        System.out.println(t);
        return t;
    }
}
package operator;

public class TestGeneric {
    public static void main(String[] args) {

        MyInterfaceImpl myInterface = new MyInterfaceImpl();
        myInterface.server("Hello");//Hello

        MyInterfaceImpl2<Integer> myInterface2 = new MyInterfaceImpl2();
        myInterface2.server(100);//100

    }
}

泛型方法

方法定义

package operator;
//泛型方法
//语法:<T>返回值
public class MyGenericMethod {
    //泛型方法
    public <T> T show(T t) {
        System.out.println("泛型方法"+t);
        return t;
    }
}
package operator;

public class TestGeneric {
    public static void main(String[] args) {
        
        MyGenericMethod gg = new MyGenericMethod();
        gg.show("中国加油");//中国加油,类型是String
        gg.show(100);//100,类型是Integer
    }
}

泛型的好处,
1、提高代码的重用性-不用重写,一个方法就可以传递不同类型的参数,不用像以前一样要重载多个方法
2、防止类型转换异常,提高代码的安全性

泛型集合

LinkedList list = new LinkedList<>();
public class LinkedList-源码
当什么类型都没传参时,默认是object,所以往里面加什么元素时,都会默认转化成object类型

package operator;

import java.util.ArrayList;

public class Demo03 {
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        arrayList.add("aaa");
        arrayList.add("bbb");
        arrayList.add(10);
        for (Object obj : arrayList) {
            System.out.println(obj);
            
        }//不会报错
        for(Object obj : arrayList){
            String str = (String) obj;
            System.out.println(str);//会报错,10无法强转为String类型
        }
        
    }
package operator;

import java.util.ArrayList;

public class Demo03 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add("aaa");
        arrayList.add("bbb");
       // arrayList.add(10);加上String后,编译时这里就会标红了,提示你要修改
       for (String str : arrayList) {
           System.out.println(str);
       }
        ArrayList<Student> arrayList2 = new ArrayList<Student>();
        arrayList2.add(new Student("Tom", 20));
        arrayList2.add(new Student("Jerry", 25));
        for (Student student : arrayList2) {
            System.out.println(student.getName() + " " + student.getAge());
        }
//aaa
//bbb
//Tom 20
//Jerry 25

    }
}

Set子接口

特喽:无序,无下标,元素不可重复
方法:全部继承Collection的方法

package base;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * set接口的使用
 *特点:无序,没有下标,元素不能重复
 *
 */
public class Demo01 {
    public static void main(String[] args) {
        // 创建set集合
        Set<String> set = new HashSet<>();
        // 添加元素
        set.add("apple");
        set.add("banana");
        set.add("orange");
        set.add("orange");
        System.out.println(set.size());
        System.out.println(set.toString());//[banana, orange, apple]无序,加多了的orange会自动去掉
        //删除
        set.remove("banana");
        System.out.println(set.toString());//[orange, apple]
        //遍历
        for (String str : set) {
                    System.out.println(str);
        }
        //迭代器
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
                    System.out.println(iterator.next());
        }
        //判断是否包含元素
        System.out.println(set.contains("apple"));//true

    }
}

HashSet-重点

1、基于Hashcode计算元素存放位置(就算重写hashcode方法,不同属性的对象仍可能存在相同hashcode,一般相同hashcode,就已经拒绝存入了,所以需要equals进行二次判断)
2、当存入元素哈希码相同时,会调用equals进行确认,如果为true,则拒绝后者存入(set是不允许重复元素)
知识补充

==和equals方法的区别,为什么重写equals还要重写hashCode?
HashSet集合中元素的添加过程

1、== 运算符
使用范围:基本数据类型和引用数据类型。
在基本数据类型中:比较的是两个变量保存的数据是否相等。
在引用数据类型中:比较的是两个对象的地址是否相同,即两个引用对象是否指向同一个对象实体。
在没有重写equals方法前,equals 和 == 都是一样的,都是比较对象的引用是否相同。(对象的内存地址)

2、每个对象都有一个默认的hashCode实现,它通常是根据对象的内存地址计算出的一个唯一标识。不同对象的 hashCode 可能相同;但 hashCode 不同的对象一定不相等。(所以hashcode不是对象的内存地址)-所以为什么不能用object的hashcode方法,他的方法就是根据内存地址计算,所以就算两个属性相同的new出来的,也会判定为不同的对象,所以要重新写hashcode方法,至少让两个对象相等先,才能走到equals方法,equals的原方法也是比较两个对象的内存地址,也是不行的,所以要重写equals方法
public boolean equals(Object obj) {
return (this == obj);
}

3、添加元素的过程:
我们向HashSet中添加元素a,首先会调用元素a所在类的hashCode()方法,计算元素a的hash值(哈希值),之后再根据得到的元素a的hash值再通过散列函数(一种算法,我们可以通过这个算法得到我们元素a在数组中应该存储的索引位置)计算出在我们的元素a在底层数组中的存放位置(也就是索引位置),再判断这个位置上是否已经有了元素了

如果此位置上没有其他元素,则元素a添加成功 ---- 情况一
如果此位置上有其他元素b(或者以链表形式存在的多个元素),则比较元素a与元素b的hash值
如果元素a和元素b的哈希值不相同,则元素a添加成功 ---- 情况二
如果元素a和元素b的哈希值相同,进而需要调用元素a所在类的equals()方法判断
如果equals()方法返回false,则元素a添加成功 ---- 情况三
如果equals()方法返回true,则元素a添加失败

4、易错点避免:

两个不同的对象,这两个不同的对象的hash值有可能是相同的
两个相同的对象,这两个对象的hash值就一定是相同的
这个就说明我们在HashSet中添加元素时即使我们的元素的索引位置相同,并且hash值也相同,也有可能不是同一对象,这个时候我们还要通过使用equals()方法判断是否是真正的同一个对象

不同的两个hash值通过散列函数计算的数组的索引位置可能相同
也就是当我们的HashSet中底层的数组中的同一索引位置中的元素可能是不同的hash值的对象,这个时候我们就要在判断一下同一位置上的元素的hash值是否相同

import java.util.HashSet;

/**
 * HashSet集合的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * 特点:无序、唯一
 */
public class Demo02 {
    public static void main(String[] args) {
        // 创建HashSet集合
        HashSet<String> set = new HashSet<>();
        // 添加元素
        set.add("apple");
        set.add("banana");
        set.add("orange");
        set.add("pear");
        System.out.println(set.toString());
    }
}
package base;

import java.util.Objects;

public class Person {
    private String name;
    private int age;
    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;
    }
    public String toString() {
            return "Name: " + name + ", Age: " + age;
    }

    @Override
    public int hashCode() {
        int n1=this.name.hashCode();//调用的是String的hashCode方法,其算法是基于字符串中每个字符的Unicode值来进行的
        int n2=this.age;
        return n1+n2;
    }
    @Override
    public boolean equals(Object obj) {//Object obj是指Hashset中已存放的对象,会把新对象和已存对象进行比较
        //// 比较当前对象与传入对象是否为同一对象
        if(this==obj){
            return true;
        }
        if(obj==null){
            return false;
        }
        if(obj instanceof Person){
            Person p=(Person)obj;
            if(this.name.equals(p.name) && this.age==p.age){
                return true;
            }
        }
        return false;
    }

}

可以利用生成方法,快速重写hashcode和equals方法,重写这两个方法是避免添加重复属性的对象

package base;

import java.util.HashSet;
import java.util.Iterator;

/**
 * HashSet集合的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * 特点:无序、唯一
 * 存储过程
 * 根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步
 * 再执行equals方法(判断两个对象hashcode是否相等),如果为true,则认为重复,否则形成链表
 */
public class Demo02 {
    public static void main(String[] args) {
        // 创建HashSet集合
        HashSet<Person> set = new HashSet<>();
        // 添加元素
        Person p1 = new Person("Jeff", 27);
        Person p2 = new Person("Jerry", 25);
        Person p3 = new Person("Tom", 20);
        Person p4 = new Person("Tom", 20);
        set.add(p1);
        set.add(p2);
        set.add(p3);

        System.out.println(p4.hashCode());
        System.out.println(p3.hashCode());
        set.add(new Person("Tom", 20));//如果不重写equals方法,虽然 hashCode 相同,但是会在同一个位置形成链表,从而加进来,如果要判定这个是重复元素不让加入,需要重写 equals 方法
        //add方法会自动调用Person类中的hashCode和equal方法
        System.out.println(set.size());
        System.out.println(set.toString());
        /**
         * 为了确定这个新对象是否已经是集合中的成员,Set会调用以下方法:
         * new Person("Tom", 20).hashCode():计算新对象的哈希码。如果不重写hashCode方法,默认的hashCode方法是基于对象的内存地址,就算两个对象有相同的属性,也可能得到不同的hashCode。
         * 对于哈希码相同的每个对象(在Set中可能有多个对象,因为哈希码碰撞是可能的),Set会调用equals方法来比较新对象和已存在的对象。
         * 如果Person类没有重写hashCode和equals方法,那么equals方法默认是比较两个对象的引用是否相同。因此,即使两个Person对象的属性相同(名字和年龄都是"Tom"和20),只要它们是不同的对象(不同的引用),它们也会被视为不同的元素。
         * 在你的代码示例中,p3和p4虽然有相同的属性,但由于它们是不同的对象,如果没有重写equals方法,p4仍然会被添加到集合中,使得集合的大小增加。
         * 因此,set.add(new Person("Tom", 20))这行代码会使用equals方法来比较新创建的Person("Tom", 20)对象和集合中已经存在的每个Person对象,以确定是否应该将其添加到集合中。如果你希望具有相同属性的对象被视为相同,你需要重写Person类的hashCode和equals方法。
         */
        //遍历
        for (Person person : set) {
                    System.out.println(person.toString());
        }
        //迭代器
        Iterator<Person> iterator = set.iterator();
        while (iterator.hasNext()) {
            Person person = iterator.next();
            System.out.println(person.toString());
        }


    }
}

TreeSet

1、基于排列顺序实现元素不重复
2、实现了SortedSet接口,对集合元素自动排序
3、元素对象的类型必须实现Comparable接口,指定排序规则
4、通过CompareTo方法确定是否为重复元素
二叉树:左小右大
红黑树:根节点是黑(在二叉树的基础再加颜色),节点有黑有红,就是为了保证结构平衡

package base;

import java.util.TreeSet;

/**
 * TreeSet使用
 * 存储结构:红黑树
 */

public class Demo04 {
    public static void main(String[] args) {
        TreeSet<String> set = new TreeSet<>();
        set.add("xyx");
        set.add("abc");
        set.add("hello");
        System.out.println(set.size());
        System.out.println(set.toString());//[abc, hello, xyx],按字母顺序排列


    }
}
package base;

import java.util.Objects;

public class Person implements Comparable<Person> {
    private String name;
    private int age;
    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;
    }
    public String toString() {
            return "Name: " + name + ", Age: " + age;
    }

  
//先按姓名比,然后再按年龄比
    @Override
    public int compareTo(Person o) {
        int n1=this.getName().compareTo(o.getName());
        int n2=this.getAge()-o.getAge();
        return n1==0?n2:n1;
    }
}
package base;

import java.util.TreeSet;
//要求:元素必须实现Comparable接口,并重写compareTo()方法,以便排序。否则再add()时会报错。compareTo()方法返回值为0,认为是重复元素




public class Demo05 {
    public static void main(String[] args) {
        TreeSet<Person> persons = new TreeSet<>();
        persons.add(new Person("John", 25));
        persons.add(new Person("Alice", 30));
        persons.add(new Person("Bob", 20));
        System.out.println(persons.size());
        System.out.println(persons.toString());


    }
}

另一种写法Comparator接口

package base;

import java.util.Comparator;
import java.util.TreeSet;
//TreeSet集合的使用
//Comparator:实现定制比较(比较器)
//Comparable:可比较的


public class Demo05 {
    public static void main(String[] args) {
        TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
//new Comparator<Person>():因为Person类没有实现Comparable接口,这里需要提供一个Comparator来定义排序规则
            @Override
            public int compare(Person o1, Person o2) {
                int n1 = o1.getName().compareTo(o2.getName());
                int n2 = o1.getAge() - o2.getAge();
                return n1 != 0 ? n1 : n2;
            }
        });
        persons.add(new Person("John", 25));
        persons.add(new Person("Alice", 30));
        persons.add(new Person("Bob", 20));
        System.out.println(persons.size());
        System.out.println(persons.toString());


    }
}

Map集合

HashMap-重点


package Map;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 特点:键值对存储,无序性,键唯一,值可重复
 */
public class Demo01 {
    public static void main(String[] args) {
        // 创建Map对象
        HashMap<String, String> map = new HashMap<>();
        //添加元素
        map.put("cn", "中国");
        map.put("uk", "英国");
        map.put("usa", "美国");
        map.put("cn", "zhongguo");//{usa=美国, uk=英国, cn=zhongguo}
        System.out.println(map.size());
        System.out.println(map.toString());//{usa=美国, uk=英国, cn=中国}

        //删除
        map.remove("cn");
        System.out.println(map.size());//2
        //遍历
        //使用keySet()
        Set<String> keyset = map.keySet();
        for (String key : keyset) {//也能写成for(String key : map.keySet())
            System.out.println(key);
            System.out.println(map.get(key));
        }
        //使用entrySet()
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }


    }
}

package Map;

import java.util.HashMap;

/**
 * HashMap集合的使用
 * 存储结构 :哈希表(数组+链表+红黑树)
 * 使用key可hashcode和equals作为重复,要重写这两个方法
 */
public class Demo02 {
    public static void main(String[] args) {
        HashMap<Student, String> students = new HashMap<>();
        Student s1 = new Student("张三", 100);
        Student s2 = new Student("李四", 101);
        Student s3 = new Student("王五", 102);
        students.put(s1, "北京");
        students.put(s2, "上海");
        students.put(s3, "深圳");
        //students.put(new Student("李四", 101), "广州"); // 要重写hashcode和equals方法,才能保证不会加入重复的new对象
        System.out.println(students.size());
        System.out.println(students.toString());
    }
}

Hashtable 较少用了

Properties 上面的子类,流的时候会用,通常用于配置文件的读取

TreeMap 实现了SortedMap接口(是Map的子接口)可以对key自动排序

package Map;

import java.util.TreeMap;

/**
 * TreeMap
 * 存储结构:红黑树
 *
 */
public class Demo03 {
    public static void main(String[] args) {
        TreeMap<Student, String> treeMap = new TreeMap<Student, String>();
        Student s1 = new Student("张三", 100);
        Student s2 = new Student("李四", 101);
        Student s3 = new Student("王五", 102);
        treeMap.put(s1, "北京");
        treeMap.put(s2, "上海");
        treeMap.put(s3, "深圳");
        System.out.println(treeMap.size());//要继承Comparable接口才能排序
        System.out.println(treeMap.toString());

    }
}

Collections工具类

除了存取以外常用的集合常用方法
package Map;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static java.util.Collections.binarySearch;

/**

  • 演示Collections工具类的使用
    */
public class Demo04 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(120);
        list.add(30);
        list.add(50);
        list.add(20);
        list.add(40);
        //sort方法
        System.out.println("排序前:" + list);//排序前:[120, 30, 50, 20, 40]
        Collections.sort(list);
        System.out.println("排序后:" + list);//排序后:[20, 30, 40, 50, 120]

        //binarySearch方法
        int i=Collections.binarySearch(list, 30);
        System.out.println("查找30的索引:" + i);//1

        //copy,这个方法有问题,不用
        //ArrayList<Integer> list2 = new ArrayList<>();
        //Collections.copy(list2, list);
        //System.out.println("复制后:" + list2);//复制后:[20, 30, 40, 50, 120]

        //reverse
        Collections.reverse(list);
        System.out.println("反转后:" + list);//反转后:[120, 50, 40, 30, 20]

        //shuffle
        Collections.shuffle(list);
        System.out.println("打乱后:" + list);//打乱后:[20, 30, 50, 120, 40]

        //补充:list转数组-指的是list接口-转后就可以直接使用数组的操作方法
        Integer[] arr = list.toArray(new Integer[10]);
        System.out.println("转数组后:" + Arrays.toString(arr));//转数组后:[40, 120, 50, 20, 30, null, null, null, null, null]
        System.out.println(arr.length);//10

        //数组转成集合
        String[] name = {"apple", "banana", "orange", "pear"};
        //集合是一个受限集合,不能添加和删除元素,只能读取元素
        List<String> list1 = Arrays.asList(name);
        System.out.println(list1);  //[apple, banana, orange, pear]
        //基本类型数组转集合,需要修改为包装类型
        Integer[] arr1 = {1, 2, 3, 4, 5};
   
    }
}

数组和集合的区别
数组存放基本类型和引用类型,一旦创建了长度就不能变了,大小不能更改
集合主要是存放引用类型数据,可以随时加入元素

posted @ 2025-01-13 19:25  乘加法  阅读(37)  评论(0)    收藏  举报