Java基础学习(8)---Java集合类

一、集合的概念

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

和数组的区别

  • 数组长度固定,集合长度不固定。
  • 数组可以存储基本类型和引用类型,集合只能存储引用类型。

位置java.util.*;

二、Collection接口

在这里插入图片描述

  • 特点:代表一组任意类型的对象,无序、无下标、不能重复。
  • 创建集合:Collection collection = new ArrayList();

常用方法

方法作用
boolean add(Object obj)添加一个对象
boolean addAll(Collection c)将一个集合中的所有对象添加到此集合中
void clear()清空此集合中的所有对象
boolean contains(Object obj)检查此集合是否包含指定对象
boolean equals(Object o)比较此集合是否与指定对象相等
boolean isEmpty()判断此集合是否为空
int size()返回此集合中的元素个数
Object[] toArray()将此集合转换成数组(类型为Object)
    public static void main(String[] args) {
        //Collection接口的使用
        //创建集合  Collection不能直接实例化
        Collection collection = new ArrayList();
        //1 添加元素
        collection.add("苹果");
        collection.add("芒果");
        collection.add("榴莲");
        //添加对象
       //Student student=new Student("aaa",20);
       //collection.add(student);
        System.out.println("元素个数:"+collection.size());//元素个数:3
        System.out.println(collection);//相当于调用toString()方法  [苹果, 芒果, 榴莲]
        //2 删除元素
        //collection.remove("苹果");
        //System.out.println("删除后的元素个数:"+collection.size());//删除后的元素个数:2
        //collection.clear();//清空
        //clear(); 只是清空集合存储的地址值!
        //3 遍历 ★
        //3.1 使用增强for
        for (Object object:collection) {
            System.out.println(object);
        }
        //3.2 使用迭代器(迭代器是专门用来遍历集合的一种方式)
        Iterator it=collection.iterator();//Iterator是一个接口
        //迭代器的三种方法:
        //haNext(); 有没有下一个元素
        //next(); 获取下一个元素 返回的是Object类型
        //remove(); 删除当前元素
        while(it.hasNext()){
            String object = (String)it.next(); //强转
            System.out.println(object);
            //在迭代过程中不能使用collection的方法来改变集合的元素
            //collection.remove(); 不能用collection其他方法 会报并发修改异常
            //但可以使用it.remove(); 进行移除元素
        }
        //4 判断
        System.out.println(collection.contains("苹果"));//true
        System.out.println(collection.isEmpty());//false
    }

三、List接口与实现类

List接口

  • 特点:有序、有下标、元素可重复。
  • 创建集合对象:List list = new ArrayList<>( );

常用方法

方法作用
void add(int index,Object obj)在index位置插入一个对象obj
boolean addAll(int index,Collection c)将一个集合中的元素添加到此集合中的index位置
void clear()清空此集合中的所有对象
Object get(int index)返回集中中指定位置的元素
List subList(int fromIndex,int toIndex)返回fromIndex和toIndex之间的集合元素

注:List继承了Collection接口的所有方法,还包含了以上的方法。

    public static void main(String[] args) {
        //List子接口的使用
        //创建集合对象
        List list = new ArrayList<>( );
        //1 添加元素
        list.add("芒果");
        list.add("榴莲");
        list.add(0,"葡萄");//在第一个位置插入元素
        //添加基本数据类型时,会对基本类型进行自动装箱!!!
        //list.add(20);
        System.out.println("元素个数:"+list.size());//元素个数:3
        System.out.println(list.toString());//[葡萄, 芒果, 榴莲]
        //2 删除元素
        //list.remove("葡萄");
        //list.remove(0);//删除第一个元素
        //当删除数字与索引矛盾时 对数字强转
        //list.remove((Object) 20) 或 list.remove(new Integer(20))
        //System.out.println("元素个数:"+list.size());//元素个数:2
        //System.out.println(list.toString());//[芒果, 榴莲]
        //3 遍历
        //3.1 使用for遍历
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));//get() 返回的是Object类型
        }
        //3.2 使用增强for
        for (Object object:list) {
            System.out.println(object);
        }
        //3.3 使用迭代器
        Iterator it=list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        //3.4 使用列表迭代器 ★
        //和迭代器iterator的区别:
        //listIterator可以向前或向后遍历,还可以添加、删除和修改元素
        ListIterator li=list.listIterator();
        while(li.hasNext()){
            System.out.println(li.nextIndex() + ":" + li.next()); //从前往后遍历
            //nextIndex下一个元素的角标
        }
        while(li.hasPrevious()){
            System.out.println(li.previousIndex() + ":" + li.previous()); //从后往前遍历
        }
        //4 判断
        System.out.println(list.contains("葡萄"));//true
        System.out.println(list.isEmpty());//false
        //5 获取位置
        System.out.println(list.indexOf("芒果"));//1
        //6 返回子集合 sublist(x, y); 左闭右开
        //list 20 30 40 50
        //List subList = list.subList(1, 3); 返回索引 1、2
        //subList 30 40
    }

List实现类

  • ArrayList 【重点】
    • 由数组结构实现,必须要连续空间,查询快、增删慢。
    • jdk1.2版本,运行效率快、线程不安全。
  • Vector:
    • 数组结构实现,查询快、增删慢。
    • jdk1.0版本,运行效率慢,线程安全。
  • LinkedList:
    • 由双向链表结构实现,无需连续空间,增删快,查询慢。

ArrayList

    public static void main(String[] args) {
        //ArrayList的使用
        //创建集合
        ArrayList arrayList = new ArrayList<>();
        //1 添加元素
        Student s1=new Student("aaa",12);
        Student s2=new Student("bbb",14);
        Student s3=new Student("ccc",10);
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        System.out.println("元素个数:"+arrayList.size());//元素个数:3
        System.out.println(arrayList.toString());
        //2 删除元素
        //arrayList.remove(s1);
        //System.out.println("元素个数:"+arrayList.size());//元素个数:2
        //arrayList.remove(new Student("aaa",12));//若想实现此行代码,需要重写equals方法
        //remove方法实际上会调用 equals(this==obj) 比较的是地址
        //System.out.println("元素个数:"+arrayList.size());//元素个数:2
        //arrayList.clear();//清空
        //3 遍历元素 ★
        //3.1 使用迭代器
        Iterator it=arrayList.iterator();
        while(it.hasNext()){
            Student s=(Student)it.next();
            System.out.println(s.toString());
        }
        //3.2 使用列表迭代器
        ListIterator li=arrayList.listIterator();
        while(li.hasNext()){//顺序
            Student s=(Student)li.next();
            System.out.println(s.toString());
        }
        while(li.hasPrevious()){//逆序
            Student s=(Student)li.previous();
            System.out.println(s.toString());
        }
        //4 判断
        System.out.println(arrayList.contains(new Student("aaa",12)));//true  因为判断的规则已经被修改了
        System.out.println(arrayList.isEmpty());//false
        //5 查找
        System.out.println(arrayList.indexOf(new Student("aaa",12)));//0
    }
    @Override
    public boolean equals(Object obj){
        //1 判断是不是同一个对象
        if(this == obj){
            return true;
        }
        //2 判断是否为空
        if(obj == null){
            return false;
        }
        //3 判断obj是否是Student类型
        if(obj instanceof Student){
            Student s = (Student)obj;
            //4 比较属性
            if(this.name.equals(s.getName()) && this.age == s.getAge()){
                return true;
            }
        }
        //5 不满足条件返回false
        return false;
    }

源码分析:

DEFAULT_CAPACITY = 10; //默认容量
//注意:如果没有向集合中添加任何元素时,容量0,添加一个后,容量为10
//每次扩容是原来的1.5倍
Object[] elementData//存放元素的数组
size//实际元素个数
add()//添加元素

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
         newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
         newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

Vector

    public static void main(String[] args) {
        //Vector集合的使用
        //创建集合
        Vector vector = new Vector<>();
        //1 添加元素
        vector.add("芒果");
        System.out.println("元素个数:"+vector.size());//元素个数:1
        System.out.println(vector.toString());//[芒果]
        //2 删除 和ArrayList的一样
        //3 遍历
        //可以使用for、增强for、迭代器遍历,用法参考和ArrayList的一样
        //使用枚举器
        Enumeration en = vector.elements();
        while(en.hasMoreElements()){
            String o = (String)en.nextElement();
            System.out.println(o);
        }
        //4 判断和查找同理
        //补充
        vector.firstElement();//得到第一个元素
        vector.lastElement();//得到最后一个元素
        vector.elementAt(0);//获取第一个位置的元素 get()
    }

LinkedList

    public static void main(String[] args) {
        //LinkedList集合的使用
        //创建集合
        LinkedList li = new LinkedList<>();
        //用法和ArrayList一致!!
    }

ArrayList与LinkedList的区别
在这里插入图片描述

四、泛型

  • Java 泛型是JDK1.5引入的一个新特性,其本质是参数化类型,即把类型作为参数传递。
  • 常见形式有泛型类、泛型接口、泛型方法。
  • 语法:<T,…> T称为类型占位符,表示一种引用类型。
  • 好处:
    • 提高代码的重用性。
    • 防止类型转换异常,提高代码的安全性。

泛型类

//泛型类
//语法:类名<T,E>
//T是类型占位符,表示一种引用类型,如果编写多个,需使用逗号隔开
public class MyGeneric<T>{
    //T表示一种类型,使用泛型T
    //1 创建变量
    T t;
    //2 泛型作为方法的参数
    public void show(T t){
        //T t=new t();//不能实例化!!
        System.out.println(t);
    }
    //3 泛型作为方法的返回值
    public T getT(){
        return t;
    }
}
    public static void main(String[] args) {
        //使用泛型类创建对象
        // 注意: 1. 泛型只能使用引用类型
        //		  2. 不用泛型类型对象之间不能相互赋值!
        MyGeneric<String> myGeneric = new MyGeneric<String>();
        myGeneric.t = "hello";
        myGeneric.show("hello world");
        String string = myGeneric.getT();

        MyGeneric<Integer> myGeneric2 = new MyGeneric<Integer>();
        myGeneric2.t = 100;
        myGeneric2.show(200);
        Integer integer = myGeneric2.getT();
    }

泛型接口

//泛型接口
//语法:接口名<T>
public interface MyInterface<T> {

    String name="aaa";
    //T t;//注意:不能定义泛型静态常量!!
    
    T server(T t);
}
//使用泛型接口  第一种方式
public class MyInterfaceImpl implements MyInterface<String>{
    
    @Override
    public String server(String s) {
        System.out.println(s);
        return s;
    }
}

public class Test {
    public static void main(String[] args) {
        MyInterfaceImpl impl=new MyInterfaceImpl();
        impl.server("aaa");
    }
}
//使用泛型接口  第二种方式
public class MyInterfaceImpl<T> implements MyInterface<T>{

    @Override
    public T server(T t) {
        System.out.println(t);
        return t;
    }
}
public class Test {
    public static void main(String[] args) {
        MyInterfaceImpl<Integer> impl=new MyInterfaceImpl<>();
        impl.server(100);
    }
}

泛型方法

//泛型方法
//语法:放在方法的返回值前面
//  <T> 返回值类型
public class MyGenericMethod {
    //泛型方法
    public <T> T show(T t){
        System.out.println("泛型方法" + t);
        return t;
    }
}
public class Test {
    public static void main(String[] args) {
        //调用泛型方法
        MyGenericMethod myGenericMethod = new MyGenericMethod();
        myGenericMethod.show("字符串");// 自动类型为字符串
        myGenericMethod.show(100);// integer类型
        myGenericMethod.show(3.14);// double类型
    }
}

泛型集合

概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。
特点

  • 编译时即可检查,而非运行时抛出异常。
  • 访问时,不必类型转换(拆箱)。
  • 不同泛型之间应用不能相互赋值,泛型不存在多态。
    public static void main(String[] args) {
        ArrayList arrayList=new ArrayList();
        //可以添加任何类型,但是在遍历时进行类型转换时很容易出现类型转换异常!
        arrayList.add("aa");
        arrayList.add(111);
        //泛型集合  在编译时已经确认了类型
        ArrayList<String> arrayList1=new ArrayList<>();
        //只能添加String类型的!
        arrayList1.add("aaa");
        arrayList1.add("bbb");
    }

五、Set接口与实现类

Set

特点:无序、无下标、元素不可重复。
方法:全部继承自Collection中的方法(没有提供其他的方法)。

Set实现类

  • HashSet 【重点】
    • 基于HashCode实现元素不重复。
    • 当存入元素的哈希码(HashCode)相同时,会调用equals进行判断,如果为true,则拒绝后者写入。
  • TreeSet
    • 基于排列顺序实现元素不重复。
    • 实现了SortedSet接口,对集合元素自动排序。
    • 元素对象的类型必须实现Comparable接口,指定排序规则。
    • 通过CompareTo方法确定是否为重复元素。
    public static void main(String[] args) {
        //Set接口的使用
        //创建集合
        Set<String> set=new HashSet<>();
        //1 添加数据
        set.add("cc");
        set.add("aa");
        set.add("小米");
        set.add("bb");
        System.out.println("元素个数:"+set.size());//元素个数:3
        System.out.println(set.toString());//[cc, aa, bb, 小米]
        //2 删除数据
        //set.remove("cc");
        //set.clear();
        //3 遍历
        //3.1 增强for
        for (String string:set) {
            System.out.println(string);
        }
        //3.2 使用迭代器
        Iterator<String> it=set.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        //4 判断
        System.out.println(set.contains("aa"));//true
        System.out.println(set.isEmpty());//false
    }

HashSet

    public static void main(String[] args) {
        //HashSet接口的使用
        //存储结果:哈希表(数组+链表+红黑树(jdk1.8之后))
        //创建集合  增、删、遍历、判断与collection的用法一致!!
        //HashSet<String> hashSet=new HashSet<String>();//在jdk1.8之后可以不用写了
        HashSet<String> hashSet=new HashSet<>();
        //1 添加数据
        hashSet.add("苹果");
        hashSet.add("芒果");
        hashSet.add("榴莲");
        System.out.println("数据个数:"+hashSet.size());//元素个数:3
        System.out.println(hashSet.toString());//[苹果, 榴莲, 芒果]
        //2 删除数据
        //hashSet.remove("榴莲");
        //System.out.println("数据个数:"+hashSet.size());//元素个数:2
        //hashSet.clear();
        //System.out.println("数据个数:"+hashSet.size());//元素个数:0
        //3 遍历操作
        //3.1 增强for
        for (String string:hashSet) {
            System.out.println(string);
        }
        //3.2 使用迭代器
        Iterator<String> it=hashSet.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        //4 判断
        System.out.println(hashSet.contains("苹果"));//true
        System.out.println(hashSet.isEmpty());//false
    }

存储过程(重复依据):

  1. 根据hashCode计算保存的位置,如果此位置为空,则直接保存,如果不为空,则执行第二步。
    (1)利用31这个质数(只能被1和自身整数),可以减少散列冲突。 (2)可以提高执行效率 31 * i = (i << 5) - i 转为移位操作。
  2. 再执行equals方法,如果equals为true,则认为是重复,反之形成链表。
    public static void main(String[] args) {
        //HashSet接口的使用
        //存储结果:哈希表(数组+链表+红黑树(jdk1.8之后))
        //创建集合
        //HashSet<String> hashSet=new HashSet<String>();//在jdk1.8之后可以不用写了
        HashSet<Student> hashSet=new HashSet<>();
        Student s1=new Student("aaa",11);
        Student s2=new Student("bbb",14);
        Student s3=new Student("ccc",17);
        //1 添加数据
        hashSet.add(s1);
        hashSet.add(s2);
        hashSet.add(s3);
        //hashSet.add(s3);//重复,无法添加
        //hashSet.add(new Student("aaa",11));//可以添加
        //重写hashCode和equals后,上诉代码无法被添加

        System.out.println("数据个数:"+hashSet.size());//元素个数:3
        System.out.println(hashSet.toString());
        //2 删除操作
        //hashSet.remove(new Student("aaa",11));//没有重写hashCode和equals之前,这样的写法无法删除s1
    }
    @Override
    public boolean equals(Object obj){
        //1 判断是不是同一个对象
        if(this == obj){
            return true;
        }
        //2 判断是否为空
        if(obj == null){
            return false;
        }
        //3 判断obj是否是Student类型
        if(obj instanceof Student){
            Student s = (Student)obj;
            //4 比较属性
            if(this.name.equals(s.getName()) && this.age == s.getAge()){
                return true;
            }
        }
        //5 不满足条件返回false
        return false;
    }

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

TreeSet

    public static void main(String[] args) {
        //TreeSet的使用
        //存储结构:红黑树
        //创建集合
        TreeSet<String> treeSet = new TreeSet<>();
        //1 添加数据
        treeSet.add("xyz");
        treeSet.add("abc");
        treeSet.add("hello");
        //treeSet.add("xyz");//不再添加
        System.out.println("数据个数:"+treeSet.size());//数据个数:3
        System.out.println(treeSet.toString());//[abc, hello, xyz]   自动排序
        //2 删除数据
        //treeSet.remove("abc");
        //treeSet.clear();
        //3 遍历操作
        //3.1 增强for
        for (String string:treeSet) {
            System.out.println(string);
        }
        //3.2 迭代器
        Iterator<String> it=treeSet.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        //4 判断
        System.out.println(treeSet.contains("abc"));//true
        System.out.println(treeSet.isEmpty());//false
    }

补充:TreeSet集合的使用

  • Comparator 实现定制比较(比较器)
  • Comparable 可比较的

Comparable

public class Student implements Comparable<Student>{
    //先按姓名比,再按年龄比
    @Override
    public int compareTo(Student o) {
        int n1 = this.getName().compareTo(o.getName());
        int n2 = this.getAge()-o.getAge();
        return n1 == 0 ? n2 : n1;
    }
}
    public static void main(String[] args) {
        //TreeSet的使用
        //存储结构:红黑树
        //要求:元素对象的类型必须实现Comparable接口
        //compareTo()方法的返回值为0,认为是重复元素
        //创建集合
        TreeSet<Student> treeSet = new TreeSet<>();
        Student s1=new Student("aaa",13);
        Student s2=new Student("bbb",15);
        Student s3=new Student("ccc",17);
        Student s4=new Student("ccc",18);
        //1 添加数据
        treeSet.add(s1);
        treeSet.add(s2);
        treeSet.add(s3);
        treeSet.add(s4);
        System.out.println("数据个数:"+treeSet.size());//数据个数:3
        System.out.println(treeSet.toString());
        //[Student{name='aaa', age=13}, Student{name='bbb', age=15}, Student{name='ccc', age=17}, Student{name='ccc', age=18}]
        //2 删除数据
        //treeSet.remove(new Student("aaa",13));//可以删除s1
        //System.out.println(treeSet.contains(new Student("aaa",13)));//true
        //是根据compareTo()方法来比较的
    }

Comparator

    public static void main(String[] args) {
        //TreeSet的使用
        //存储结构:红黑树
        //Comparator:实现定制比较(比较器)
        //创建集合,并指定比较规则,这样Student可以不用实现Comparable接口
        TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int n1 = o1.getAge()-o2.getAge();
                int n2 = o1.getName().compareTo(o2.getName());
                return n1 == 0 ? n2 : n1;
            }
        });
        Student s1=new Student("aaa",13);
        Student s2=new Student("bbb",15);
        Student s3=new Student("ccc",17);
        Student s4=new Student("ccc",18);
        //1 添加数据
        treeSet.add(s1);
        treeSet.add(s2);
        treeSet.add(s3);
        treeSet.add(s4);
        System.out.println(treeSet.toString());
    }

案例:

    public static void main(String[] args) {
        //要求:使用TreeSet集合实现字符串按照长度进行排序
        //helloworld zhang lisi wangwu xian ba
        TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int n1=o1.length()-o2.length();
                int n2=o1.compareTo(o2);
                return n1==0?n2:n1;
            }
        });
        //添加数据
        treeSet.add("helloworld");
        treeSet.add("zhang");
        treeSet.add("lisi");
        treeSet.add("wangwu");
        treeSet.add("xian");
        treeSet.add("ba");
        System.out.println(treeSet.toString());
        //[ba, lisi, xian, zhang, wangwu, helloworld]
    }

六、Map接口与实现类

Map

在这里插入图片描述
Map接口的特点

  • 存储一对数据(Key-Value),无序、无下标,键不可重复,值可以重复。
方法作用
V put(K key,V value)将对象存入到集合中,关联键值,Key 重复会覆盖掉原值
Object get(Object key)根据键获取对应的值
Set< K> keySet()返回所有Key
Collection< V> values()返回包含所有值的Collection集合
Set<Map.Entry<K,V>> entrySet()键值匹配的Set集合
    public static void main(String[] args) {
        //Map接口的使用
        //创建Map集合
        Map<String, String> map = new HashMap<>();
        //1 添加元素
        map.put("cn", "中国");
        map.put("uk", "英国");
        map.put("usa","美国");
        System.out.println("元素个数:"+map.size());//元素个数:3
        System.out.println(map.toString());//{usa=美国, uk=英国, cn=中国}
        map.put("cn", "zhongguo"); // 会替换第一个的值
        System.out.println(map.toString());//{usa=美国, uk=英国, cn=zhongguo}
        //2 删除
        //map.remove("uk");//根据Key删除
        //map.clear();
        //3 遍历
        //3.1 使用KeySet()
        //Set<String> keyset = map.keySet(); // 所有Key的set集合
        for(String key : map.keySet()){
            System.out.println(key + "---" + map.get(key));
        }
        //3.2 使用entrySet()
        //Set<Map.Entry<String, String>> entries = map.entrySet();
        //Entry<String, String>包含一个键值对
        for(Map.Entry<String, String> entry : map.entrySet()){
            System.out.println(entry.getKey() + "---" + entry.getValue());
        }
        //4 判断
        System.out.println(map.containsKey("cn"));//true
        System.out.println(map.containsValue("法国"));//false
    }

在这里插入图片描述

Map实现类

  • HashMap【重点】
    • JDK1.2版本,线程不安全,运行效率快;允许用null作为Key或Value。
  • Hashtable
    • JDK1.0版本,线程安全,运行效率慢;不允许用null作为Key或Value。
  • Properties
    • Hashtable 子类,要求Key和Value都是String;通常用于资源或配置文件的读写。
  • TreeMap
    • 实现了SortedMap接口(是Map的子接口),可以对Key自动排序。

HashMap

    public static void main(String[] args) {
        //HashMap集合的使用
        //存储结构:哈希表=数组+链表+红黑树
        //使用key的hashcode和equals作为重复依据
        //创建集合
        HashMap<Student,String> hashMap=new HashMap<>();
        Student s1=new Student("aaa",11);
        Student s2=new Student("bbb",14);
        Student s3=new Student("ccc",17);
        //1 添加数据
        hashMap.put(s1,"北京");
        hashMap.put(s2,"上海");
        hashMap.put(s3,"杭州");
        System.out.println("数据个数:"+hashMap.size());//数据个数:3
        System.out.println(hashMap.toString());
        //{Student{name='ccc', stuNo=17}=杭州, Student{name='bbb', stuNo=14}=上海, Student{name='aaa', stuNo=11}=北京}
        hashMap.put(new Student("ccc",17),"唐山");//要想这个加不进集合,就要重写hashcode和equals
        //System.out.println("数据个数:"+hashMap.size());//数据个数:4
        System.out.println("数据个数:"+hashMap.size());//数据个数:3   重写后就无法添加了!
        //2 删除数据
        //hashMap.remove(s1);
        //hashMap.clear();
        //3 遍历
        //3.1 使用KeySet()
        for(Student key : hashMap.keySet()){
            System.out.println(key + "---" + hashMap.get(key));
        }
        //3.2 使用entrySet()
        for(Map.Entry<Student, String> entry : hashMap.entrySet()){
            System.out.println(entry.getKey() + "---" + entry.getValue());
        }
        //4 判断
        System.out.println(hashMap.containsKey(s1));//true
        System.out.println(new Student("aaa",11));//因为重写hashcode和equals  true
        System.out.println(hashMap.containsValue("武汉"));//false
    }
public class Student {
    @Override
    public boolean equals(Object obj){
        //1 判断是不是同一个对象
        if(this == obj){
            return true;
        }
        //2 判断是否为空
        if(obj == null){
            return false;
        }
        //3 判断obj是否是Student类型
        if(obj instanceof Student){
            Student s = (Student)obj;
            //4 比较属性
            if(this.name.equals(s.getName()) && this.stuNo == s.getStuNo()){
                return true;
            }
        }
        //5 不满足条件返回false
        return false;
    }

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

源码分析总结

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//hashMap初始容量大小
static final int MAXIMUM_CAPACITY = 1 << 30;//hashMap的数组最大容量
static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
static final int TREEIFY_THRESHOLD = 8;//jdk1.8 当链表长度大于8时,调整为红黑树
static final int UNTREEIFY_THRESHOLD = 6;//jdk1.8 当链表长度小于6时,调整为链表
static final int MIN_TREEIFY_CAPACITY = 64;//jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整为红黑树
transient Node<K,V>[] table;//哈希表中的数组
transient int size;//元素个数
  • HashMap刚创建时,table是null,是为了节省空间。当添加第一个元素时,table容量调整为16。
  • 当元素个数大于阈值(16*0.75 = 12)时,会进行扩容,扩容后的大小为原来的2倍,目的是减少调整元素的个数。
  • jdk1.8 当每个链表长度 >8 ,并且数组元素个数 ≥64时,会调整为红黑树,目的是提高效率。
  • jdk1.8 当链表长度 <6 时,调整成链表。
  • 在jdk1.8 以前,链表时头插入,之后为尾插入。

注意:HashSet 内部用的就是HashMap。

TreeMap

存储结构:红黑树;可以对key自动排序。

    public static void main(String[] args) {
        //TreeMap的使用
        TreeMap<Student,String> treeMap=new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int n2=o1.getStuNo()-o2.getStuNo();
                return n2;
            }
        });
        Student s1=new Student("aaa",11);
        Student s2=new Student("bbb",14);
        Student s3=new Student("ccc",17);
        //1 添加数据
        treeMap.put(s1,"南宁");
        treeMap.put(s2,"上海");
        treeMap.put(s3,"杭州");
        System.out.println("数据个数:"+treeMap.size());//数据个数:3
        System.out.println(treeMap.toString());
        //{Student{name='aaa', stuNo=11}=南宁, Student{name='bbb', stuNo=14}=上海, Student{name='ccc', stuNo=17}=杭州}
        treeMap.put(new Student("ccc",17),"武汉");
        System.out.println(treeMap.toString());
        //{Student{name='aaa', stuNo=11}=南宁, Student{name='bbb', stuNo=14}=上海, Student{name='ccc', stuNo=17}=武汉}
        //2 删除数据
        //treeMap.remove(s1);
        //treeMap.clear();
        //treeMap.remove(new Student("ccc",17));//可以删除s3
        //3 遍历
        //3.1 使用KeySet()
        for(Student key : treeMap.keySet()){
            System.out.println(key + "===" + treeMap.get(key));
        }
        //3.2 使用entrySet()
        for(Map.Entry<Student, String> entry : treeMap.entrySet()){
            System.out.println(entry.getKey() + "===" + entry.getValue());
        }
        //4 判断
        System.out.println(treeMap.containsKey(s1));//true
        System.out.println(new Student("aaa",11));//true
        System.out.println(treeMap.containsValue("重庆"));//false
    }

注意:TreeSet 内部用的就是TreeMap!!

七、Collections工具类

概念:集合工具类,定义了除了存取以外的集合常用方法。

方法作用
public static void reverse(List<?> list)反转集合中元素的顺序
public static void shuffle(List<?> list)随机重置集合元素的顺序
public static void sort(List< T> list)升序排序(元素类型必须实现Comparable接口)
    public static void main(String[] args) {
        //Collections工具类的使用
        List<Integer> list=new ArrayList<>();
        list.add(20);
        list.add(5);
        list.add(12);
        list.add(30);
        list.add(6);

        //sort排序
        System.out.println("排序之前"+list.toString());//排序之前[20, 5, 12, 30, 6]
        Collections.sort(list);
        System.out.println("排序之后"+list.toString());//排序之后[5, 6, 12, 20, 30]

        //二分查找binarySearch  必须要先排序
        //若找到了,值大于0;反之则小于0
        System.out.println(Collections.binarySearch(list,12));//2
        System.out.println(Collections.binarySearch(list,14));//-4

        //copy复制  前提是两个数组大小相等
        List<Integer> dest=new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            dest.add(0);
        }
        Collections.copy(dest,list);
        System.out.println(dest.toString());//[5, 6, 12, 20, 30]

        //反转reverse
        Collections.reverse(list);
        System.out.println("反转之后:"+list.toString());//反转之后:[30, 20, 12, 6, 5]

        //shuffle打乱
        Collections.shuffle(list);
        System.out.println("打乱之后:"+list.toString());//打乱之后:[20, 12, 6, 30, 5]

        //补充
        //list转成数组
        Integer[] arr = list.toArray(new Integer[10]);
        System.out.println(arr.length);//10
        System.out.println(Arrays.toString(arr));//[20, 12, 6, 30, 5, null, null, null, null, null]

        //数组转成集合
        //此时为受限集合,不能进行添加和删除操作!!
        String[] name = {"张三","李四","王五"};
        List<String> list2 = Arrays.asList(name);
        System.out.println(list2.toString());//[张三, 李四, 王五]

        //把基本类型数组转为集合时,需要修改为包装类
        Integer[] nums = {100, 200, 300, 400, 500};
        List<Integer> list3 = Arrays.asList(nums);
        System.out.println(list3.toString());//[100, 200, 300, 400, 500]
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值