Java集合框架

Java集合框架

集合的概念

  • 概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能
  • 和数组的区别
    • 数组长度固定(定义好之后就不能改变长度),集合长度不固定
    • 数组可以存储基本类型和引用类型,集合只能储存引用类型(要用集合储存基本类型,需要先把基本类型装箱转化成引用类型)
  • 位置:java.util.*;

Collection接口

在这里插入图片描述

  • 特点:代表一组任意类型的对象,无序,无下表,不能重复

  • 方法:

    • boolean add(Object obj) 添加一个对象

    • boolean addAll(Collection c) 将一个集合中的所有对象添加到此集合中

    • void clear() 清空此集合中的所有对象

    • boolean contains(Object o) 判断此集合中是否包含o对象

    • boolean equals(Object o) 比较此集合是否与指定对象相等

    • booleanisEmpty() 判断此集合是否为空

    • boolean remove(Object o) 在此集合中移除指定对象

    • int size() 返回此集合中元素的个数

    • Object [] toArray() 将此集合转换成数组

    • iterator() 迭代器

      • 迭代器中有三个方法:hasNext() 如果仍有元素可以迭代,返回true

        ​ next() 返回迭代的下一个元素

        ​ remove() 从迭代器指向的collection中移除迭代器返回的最后一个元素(可选操作)

        迭代过程中要删除元素,不能用collection的remove,只能用迭代器iterator的remove

    /*
    * Collection接口的使用     操作元素
    * 1.添加元素
    * 2.删除元素
    * 3.遍历元素
    * 4.判断
    * */
    public class Demo01 {
        public static void main(String[] args) {
            //创建集合
            Collection collection=new ArrayList();
             //* 1.添加元素
            collection.add("苹果");
            collection.add("西瓜");
            collection.add("香蕉");
            collection.add("梨子");
            System.out.println("元素个数"+collection.size());
            System.out.println(collection);
    
             //* 2.删除元素
            collection.remove("西瓜");
            System.out.println("元素个数"+collection.size());
            System.out.println(collection);
    
            //* 3.判断
            System.out.println("判断是否有香蕉"+collection.contains("香蕉"));
            System.out.println("判断是否为空"+collection.isEmpty());
    
             //* 4.遍历元素
            //增强for循环
            for (Object o : collection) {
                System.out.println("增强for  "+o);
            }
    
            // 迭代器Iterator
            Iterator it = collection.iterator();
            while(it.hasNext()){                                //hasNext() 判断是否有下一个元素
                System.out.println("迭代器  "+it.next());      //next()    获取下一个元素
                it.remove();                                    //迭代中删除;迭代完了也就删除完了
            }
            System.out.println("元素个数"+collection.size());
    
        }
    }
    
    /**
     * Collection的使用:保存学生信息    操作对象
     */
    public class Demo02 {
        public static void main(String[] args) {
            //新建collection对象
            Collection collection = new ArrayList();
            Student s1 = new Student("果果",3);
            Student s2 = new Student("欢欢",2);
            Student s3 = new Student("小黑",4);
            //1.添加数据
            collection.add(s1);
            collection.add(s2);
            collection.add(s3);
            System.out.println(collection.toString());
            collection.remove(s1);
            System.out.println("删除之后"+collection.toString());
            //collection.remove(new Student("小黑",4));
            //System.out.println("再次删除之后"+collection.toString());  之前小黑那条数据还在
    
            //2.遍历
            //增强for
            for (Object o : collection) {
                System.out.println("增强for  "+o);
            }
            //迭代器
            Iterator it = collection.iterator();
            while (it.hasNext()){
                System.out.println("迭代器  "+it.next());
            }
    
            //3.判断
            System.out.println(collection.contains(s1));        //判断是否包含对象s1
            System.out.println(collection.isEmpty());           //判断集合是否为空
    
            //4.清空  实际只是将对象从集合中移除;但对象实际还存在
            collection.clear();
            System.out.println(collection.size());         //0
            System.out.println(s2.getName());              //欢欢  clear清空后集合长度已经变0了,但是另外操作对象s2依然可以操作
        }
    }
    

List接口与实现类

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

  • 方法:

    • 包含collection的所有方法
    • void add(int index,Object o) 在指定角标处插入对象
    • boolean addAll(int index ,Collection c) 将一个集合中的元素添加到次集合的index位置
    • Object get(int index) 获取指定角标处元素
    • List subList(int fromIndex,int toIndex) 返回fromIndex(含)和toIndex(不含)角标之间的集合元素
  • List遍历方法

    • 增强for
    • iterator
    • 普通for:由于有角标,可以使用普通for遍历
    • 列表迭代listIterator():可以指定迭代方向(前–>后 或者 后–>前 都行);类带过程中可使用的方法如下
      • add() 将指定的元素插入列表
      • hasNext() 正向遍历
      • hasPrevious () 反向遍历 使用这个反向迭代需要与previous 配合;且需要先正向迭代把指针移动到最后面去才能开始反向迭代
      • next() 返回下一个元素
      • previous() 返回上一个元素
      • nextIndex() 返回下一个元素的角标
      • previousIndex() 返回上一个元素的角标
      • remove() 在列表中移除由next或previous返回的最后一个元素
      • set() 用指定元素替换next或previous返回的最后一个元素
/*
* List子接口的使用
* 特点1.有序,有角标   2.可以重复
* */
public class Demo03 {
    public static void main(String[] args) {
        //创建集合对象
        List list = new ArrayList();
        //1.添加元素
        list.add("苹果");
        list.add("香蕉");
        list.add("橘子");
        list.add(0,"西瓜");           //在0角标处添加
        list.add("苹果");                            //与前面的重复
        System.out.println(list.size());     //5
        System.out.println(list);            //[西瓜, 苹果, 香蕉, 橘子, 苹果]   西瓜插到了前面;有两个苹果

        //2.遍历
        //支持增强for和迭代器
        //由于有角标,还可以使用普通for----------
        for (int i = 0; i <list.size() ; i++) {         //get() 根据角标获取元素
            System.out.println(list.get(i));
        }
        //增强for遍历------------------
        for (Object o : list) {
            System.out.println("增强for---"+o);
        }
        //迭代器-----------------------
        Iterator it = list.iterator();
        while (it.hasNext()){
            System.out.println("迭代器***"+it.next());
        }
        //列表迭代器--------------------可以指定迭代方向(前-->后  或者  后-->前  都行)
        ListIterator lit = list.listIterator();
        while(lit.hasNext()){
            System.out.println("列表迭代器------"+lit.next());
        }
        while(lit.hasPrevious()){           //使用反向迭代,必须先正向迭代把迭代器指针移到最后面去
            System.out.println("列表迭代器反向------"+lit.previousIndex()+"角标位:"+lit.previous());
        }

        //3.判断
        System.out.println(list.contains("苹果"));    //判断是否包含 苹果
        System.out.println(list.isEmpty());           //判断列表是否为空

        //获取位置
        System.out.println(list.indexOf("苹果"));     //返回 苹果 首次出现位置的角标

        //5.删除元素
        list.remove(1);         //通过角标删除
        System.out.println(list);
        list.remove("香蕉");        //通过对象名删除
        System.out.println(list);
    }
}
/*
* 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);
        list.add(70);
        list.add(80);
        list.add(90);
        System.out.println("元素个数"+list.size());
        System.out.println(list);       //[20, 30, 40, 50, 60, 70, 80, 90]

        //删除操作
        // list.remove(20);  此时是默认删除角标20的数据,而非删除数据20;会报数组角标越界异常
        list.remove((Object)20);  //将20转成Object类型以后可以删除
        System.out.println(list);       //[30, 40, 50, 60, 70, 80, 90]
        list.remove((Integer)40);   //或者将数字40转成包装类Integer类型以后也可以删除
        System.out.println(list);           //[30, 50, 60, 70, 80, 90]

        //subList方法  返回子集合
        List subList = list.subList(1, 4);          //含头不含尾
        System.out.println("子集合"+subList);      //子集合[50, 60, 70]   
    }
}

List实现类

  • ArrayList (重点)
    • 数组结构实现,查询快,增删慢
    • 源码分析
      • DEFAULT_CAPACITY=10 默认容量大小 如果没有向集合中添加任何元素时,容量为0
      • elementDatas 存放元素的数组
      • size 实际的元素个数<=容量
      • add() 添加元素
      • 扩容时每次是原来1.5倍
  • Vector:已过时
    • 数组结构实现,查询快,增删慢
    • JDK1.0版本出现,运行效率慢,线程安全
    • 特有的遍历方式:枚举器 elements() 功能与迭代器类似
  • LinkedList:
    • 链表结构实现,增删快,查询慢
ArrayList的使用
/*
* ArrayList的使用
* 储存结构:数组,查找遍历较快,增删慢
* */
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 String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    //要实现通过new一个新对象来删除相同对象,需要重写equals方法
    public boolean equals(Object obj) {
        //1.判断是不是同一个对象
        if(this==obj){
            return true;
        }
        //2.判断是否为空
        if(obj==null){
            return false;
        }
        //3.判断是否是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;
    }
}
//=============================================================================================
public class Demo05 {
    public static void main(String[] args) {
        //创建集合
        ArrayList arrayList = new ArrayList();
        //添加元素
        Student s1 = new Student("果果",3);
        Student s2 = new Student("欢欢",4);
        Student s3 = new Student("乐乐",5);
        Student s4 = new Student("小黑",6);
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        arrayList.add(s4);
        arrayList.add(s4);                          //ArrayList  有序,可以添加重复的
        System.out.println(arrayList.size());
        System.out.println(arrayList);
        //遍历    迭代器,列表迭代器,增强for,for都可以
        //此处演示迭代器
        Iterator it = arrayList.iterator();
        while(it.hasNext()){
            System.out.println("遍历----"+it.next());
        }

        //判断
        System.out.println("判断=============");
        System.out.println(arrayList.contains(s2));     //判断是否存在
        //重写了实体类中equals方法,此处可用new对象的方式判断
        System.out.println(arrayList.contains(new Student("果果",3)));

        //查找
        System.out.println("查找=============");
        System.out.println(arrayList.indexOf(s1));
        //删除
        arrayList.remove(1);                //通过下标删除元素
        System.out.println(arrayList);
        arrayList.remove(s4);
        System.out.println(arrayList);              //可以直接删除对象,但当指定对象有重复时,只会删除第一个
        //=================================================================
        要实现通过new一个新对象来删除相同对象,需要重写实体类中equals方法
        arrayList.remove(new Student("乐乐",5));      //重写了equals方法好,此时可以通过new的方式删除对象
        System.out.println(arrayList);
    }
}

Vector的使用
/*
* 演示Vertor集合的使用
* 储存结构:数组
* */
public class VertorDemo {
    public static void main(String[] args) {
        //创建集合
        Vector vector = new Vector();
        //添加元素
        vector.add("香蕉");
        vector.add("黄瓜");
        vector.add("茄子");
        vector.add("胡萝卜");
        System.out.println("元素个数"+vector.size());

        //遍历元素   枚举器
        Enumeration ele = vector.elements();
        while (ele.hasMoreElements()){
            System.out.println(ele.nextElement());
        }
        
        //判断
        System.out.println(vector.contains("香蕉"));
        System.out.println(vector.isEmpty());
        
        //删除
        vector.remove(0);
        vector.remove("胡萝卜");
    }
}
LinkedList的使用
/*
* LinkedList的使用
* 储存结构:双向链表
* */
public class LinkedListDemo {
    public static void main(String[] args) {
        //创建LinkedList
        LinkedList linkedList = new LinkedList();
        //添加元素
        Student s1 = new Student("果果",3);
        Student s2 = new Student("欢欢",4);
        Student s3 = new Student("乐乐",5);
        Student s4 = new Student("小黑",6);
        linkedList.add(s1);
        linkedList.add(s2);
        linkedList.add(s3);
        linkedList.add(s3);             //有顺序,元素可重复
        linkedList.add(s4);
        System.out.println(linkedList.size());
        System.out.println(linkedList);

        //遍历元素  for,增强for,迭代,列表迭代都可以
        for (Object o : linkedList) {
            System.out.println("增强for遍历---"+o);
        }

        //判断
        System.out.println(linkedList.contains(s4));
        System.out.println(linkedList.isEmpty());

        //删除
        System.out.println("删除后=============================");
        linkedList.remove(2);
        linkedList.remove(s3);
        linkedList.remove(new Student("小黑",6));     //因为前面重写了实体类的equals方法,
        // 此处可用这种new对象的方式删除(具体方法重写见ArrayList实例中Student类)
        System.out.println(linkedList);
    }
}

ArrayList和LinkedList不同结构的实现方式

ArrayList:必须开辟连续的空间,查询快,增删慢

LinkedList:无须开辟连续的空间,查询慢,增删快

泛型

  • 泛型是JDK1.5以后引入的新特性,本质是参数化类型,把类型作为参数传递
  • 常见形式有泛型类,泛型方法,泛型接口
  • 语法:
    • <T,…> T称为类型占位符,表示一种引用类型
  • 好处
    • 提高代码的复用性
    • 防止类型转换异常,提高代码安全性
泛型类
/*
* 泛型类
* 语法:类名<T,T>
* T是占位符    代表一种引用数据类型,可以同时有多个T,使用逗号,隔开
* */
public class MyGeneric<T>{
    //使用泛型T
    //用法1.创建变量  泛型T作为一个类型,但具体什么类型不确定,所有可以用来创建变量,但不能nwe创建对象实例化
    T t;
    //用法2.作为方法的参数
    public void show(T t){
        System.out.println(t);
    }
    //用法3.使用泛型作为方法的返回值
    public T getT(){
        return t;
    }
}
//==================================================================================================
public class TestGeneric {
    public static void main(String[] args) {
        //使用泛型类T创建对象(必须赋予T一种引用类型)   此时创建时给了它一个String类型
        //注意点:1.使用泛型只能使用引用类型  2.不同泛型类型之间不能相互赋值
        MyGeneric<String> myGeneric = new MyGeneric<String>();
        myGeneric.t="sb";       //前面赋予了String类型,后面调用变量传字符串可以变异通过
        //myGeneric.t=1;    此处传其他类型,如整数,会报红无法正常编译
        myGeneric.show("hello");
        String t = myGeneric.getT();    //调用前面写的getT方法,返回Sting类型
        System.out.println(t);

        System.out.println("===================================================");

        MyGeneric<Integer> myGeneric2=new MyGeneric<Integer>();     //创建对象时赋予Integer类型
        myGeneric2.t=10;
        myGeneric2.show(35);
        Integer t2 = myGeneric2.getT(); //调用前面写的getT方法,返回Integer类型
        System.out.println(t2);
    }
}
泛型接口
方式1 实现泛型接口的时候明确泛型类型
/*
* 泛型接口
* 语法:接口名<T>
* 接口中可以包含抽象方法和静态常量
* 注意:不能用泛型创建静态常量
* */
public interface MyInterface<T> {
    String name="果果";
    //t t=new T();   常量要求创建的时候必须初始化;使用泛型接口前,T的类型不确定,所以不能用new的方式来创建对象初始化,进而不能创建常量
    T service(T t);     //方法service  参数是T,返回值类型也是T
}
//==========================================================================================
/*
* 实现类
* 实现泛型接口的时候明确泛型类型
* */
public class MyInterfaceImpl implements MyInterface<String>{
    public String service(String t){
        System.out.println(t);
        return t;
    }
}
//==========================================================================================
//测试类
public class GenericTest {
    public static void main(String[] args) {
        MyInterfaceImpl mi = new MyInterfaceImpl();
        mi.service("guoguo");
    }
}
方式2 实现泛型接口的时候不明确泛型类型
/*
* 泛型接口
* 语法:接口名<T>
* 接口中可以包含抽象方法和静态常量
* 注意:不能用泛型创建静态常量
* */
public interface MyInterface<T> {
    String name="果果";
    //t t=new T();   常量要求创建的时候必须初始化;使用泛型接口前,T的类型不确定,所以不能用new的方式来创建对象初始化,进而不能创建常量
    T service(T t);     //方法service  参数是T,返回值类型也是T
}
//==========================================================================================
/*
* 实现类
* 实现泛型接口的时候没有明确泛型类型,之后使用该泛型类时传入了什么类型,泛型接着也就跟着什么类型
* */
public class MyInterfaceImpl2<T> implements MyInterface<T> {
    public T service(T t){
        System.out.println(t);
        return t;
    }
}
//==========================================================================================
/*
* 测试类
* 在使用这个类的时候必须明确泛型类型
* */
public class GenericTest {
    public static void main(String[] args) {
        MyInterfaceImpl2<Integer> mi2 = new MyInterfaceImpl2<Integer>();
        mi2.service(3);
    }
}
泛型方法
/*
* 泛型方法
* 语法:<T> 返回值类型    泛型放在方法返回值类型的前面
* */
public class MyGenericMethod {
    public void haha(){
        System.out.println("普通方法");
    }
    //添加一个泛型方法
    public <T> void show1(T t){
        System.out.println("泛型方法1"+t);
    }
    public <T> T show2(T t){
        System.out.println("泛型方法2"+t);
        return t;
    }
}
//=====================================================================
public class GenericTest {
    public static void main(String[] args) {
        //泛型方法
        MyGenericMethod mgm = new MyGenericMethod();
        mgm.haha();     //调用普通方法
        //下面是调用泛型方法,不用专门传类型,直接传参数,传什么类型的参数,泛型就自动变成什么类型。还能传不同类型的参数
        mgm.show1("好傻");		//传String类型参数,泛型就是String类型
        mgm.show1(3);			//同一个方法,传其他类型也可以
        mgm.show2("哟呵");
    }
}
泛型集合
  • 概念:参数化类型、类型安全的集合,强制集合元素的类型必须统一
  • 特点
    • 编译时即可检查,而非运行时再抛出异常
    • 访问时,不必类型转换(拆箱)
    • 不同泛型之间引用不能互相赋值,泛型不存在多态
public class GenericCollection {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<String>();//定义集合的时候就明确了类型String
        arrayList.add("xxx");
        arrayList.add("yyy");
        //arrayList.add(1);         传入其他类型会直接报红
        //arrayList.add(3.14);
        for (String s : arrayList) {            //增强for遍历时(iter快捷键)直接带出来的就是String类型而不是Object了
            System.out.println(s);
        }
    }
}

Set接口与实现类

  • 特点:无序、无下标、元素不可重复

  • 方法:全部继承自Collection中的方法,本身没有定义抽象

  • HsahSet【重点】

    • 基于HashCode实现元素不可重复
    • 当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后续存入
  • TreeSet

    • 基于排列顺序实现元素不重复
    • 实现了SortedSet接口,对集合元素自动排序
    • 元素对象的类型必须实现Comparable接口,指定排序规则
    • 通过ComparaTo方法确定是否为重复元素
    • TreeSet是红黑树的结构 (二叉树)
Set接口示例
public class Demo01 {
    public static void main(String[] args) {
        //创建集合
        Set<String> set = new HashSet<String>();
        set.add("香蕉");
        set.add("茄子");
        set.add("黄瓜");
        set.add("胡萝卜");
        set.add("胡萝卜");
        System.out.println(set.size());				//4								无序,不可重复
        System.out.println(set);					//[香蕉, 胡萝卜, 黄瓜, 茄子]  重复的胡萝卜只添加进去一个;打印的顺序与添加的顺序不一样
        
        //遍历    无序,支持增强for和迭代器iterator
        for (String s : set) {
            System.out.println("增强for---"+s);
        }

        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            System.out.println("迭代器***"+it.next());
        }

        //判断
        System.out.println(set.contains("香蕉"));
        System.out.println(set.isEmpty());

        //删除                因为无序,没有角标删除方法
        set.remove("胡萝卜");
        System.out.println(set);
    }
}
HashSet示例
/*
* HashSet集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
*
* */
public class Demo02 {
    public static void main(String[] args) {
        //新建集合
        HashSet<String> hashSet = new HashSet<String>();
        //添加元素
        hashSet.add("香蕉");
        hashSet.add("黄瓜");
        hashSet.add("茄子");
        hashSet.add("胡萝卜");
        hashSet.add("胡萝卜");
        System.out.println(hashSet.size());
        System.out.println(hashSet);            //[香蕉, 胡萝卜, 黄瓜, 茄子]   顺序与添加顺序不一致,无序;无重复数据

        //遍历    增强for;iterator
        for (String s : hashSet) {
            System.out.println("增强for---"+s);
        }

        Iterator<String> it = hashSet.iterator();
        while (it.hasNext()){
            System.out.println("迭代器***"+it.next());
        }

        //判断
        System.out.println(hashSet.contains("茄子"));
        System.out.println(hashSet.isEmpty());
        //删除
        hashSet.remove("胡萝卜");
        System.out.println(hashSet);
        hashSet.clear();                    //清空
        System.out.println(hashSet);
    }
}
//实体类
public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(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 "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object obj) {					//重写equals
        if (this == obj){
            return true;
        }   
        if (obj == null){
            return false;
        } 
        if(obj instanceof Person){
            Person p=(Person)obj;
            
            if(this.name.equals(p.getName())&&this.age==p.getAge()){
                return true;
            }
        }
        return false;
    }

     @Override
    public int hashCode() {				//重写hashCode
        final int prime=31;       //使用31的原因:31是个质数,减少散列冲突;提高执行效率,i*31是将左移5位再减i 即31*i=(i<<5)-i
        int result=1;
        result=prime*result+age;
        result=prime*result+((name==null) ? 0:name.hashCode());
        return result;
    }
}
//=============================================================
/*
* HashSet的使用,操作对象
* */
/*
* HashSet的使用
* HashSet存储过程分析:
* 1.根据hashCode计算保存的位置,如果此位置为空,则直接保存,如果不为空,执行下一步
* 2,。在执行equals方法,如果equals方法为true,则默认是重复,否则,形成链表
* */
public class Demo03 {
    public static void main(String[] args) {
        //创建集合
        HashSet<Person> hashSet = new HashSet<Person>();
        //添加数据
        Person p1 = new Person("果果",3);
        Person p2 = new Person("欢欢",2);
        Person p3 = new Person("乐乐",1);
        Person p4 = new Person("小黑",4);
        hashSet.add(p1);
        hashSet.add(p2);
        hashSet.add(p3);
        hashSet.add(p4);
        hashSet.add(new Person("小白",5));                //可以直接添加new的对象
        hashSet.add(new Person("小黑",4));

        System.out.println(hashSet.size());
        System.out.println(hashSet);            //如果没有重写equals和hashcode方法,此处通过new对象可以添加重复数据

        //遍历
        for (Person person : hashSet) {
            System.out.println("增强for---"+person);
        }

        Iterator<Person> it = hashSet.iterator();
        while (it.hasNext()){
            System.out.println("迭代器***"+it.next());
        }

        //判断
        System.out.println(hashSet.contains(p2));

        //删除
        hashSet.remove(p2);
        hashSet.remove(new Person("乐乐",1))		//重写equals和hashcode方法前,该操作无法删除;重写后会判断相同,能搞删除
    }
}

重写equals()和hashCode()可以在实体类中通过右键Generate–equals()and hashCode()

TreeSet示例
/*
* TresSet的使用  简单类型
* 存储结构:红黑树
*
* */
public class Demo04 {
    public static void main(String[] args) {
        //创建集合
        TreeSet<String> treeSet = new TreeSet<String>();
        //添加
        treeSet.add("zoo");
        treeSet.add("hello");
        treeSet.add("xyz");
        treeSet.add("abc");
        treeSet.add("xyz");
        System.out.println(treeSet.size());
        System.out.println(treeSet);            //[abc, hello, xyz, zoo]        实际上是有排序的;重复的xyz没有添加进来
    
        //遍历  增强for,迭代器
        for (String s : treeSet) {
            System.out.println("增强for---"+s);
        }

        Iterator<String> it = treeSet.iterator();
        while (it.hasNext()){
            System.out.println("迭代器***"+it.next());
        }

        //判断
        System.out.println(treeSet.contains("abc"));
        
        //删除
        treeSet.remove("xyz");
        System.out.println(treeSet);
    }
}
/*
*TresSet的使用  复杂类型
*存储结构:红黑树
*要求:元素必须要实现Comparable接口
*如果实体类没有实现Comparable接口并重写compareTo方法,会报类型转换异常(无法比较进而排序)
* */
//================================实体类
public class Person implements Comparable<Person>{
    private String name;
    private int age;
    public Person() {
    }
    public Person(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 "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public boolean equals(Object obj) {					//重写equals
        if (this == obj){
            return true;
        }
        if (obj == null){
            return false;
        }
        if(obj instanceof Person){
            Person p=(Person)obj;
            if(this.name.equals(p.getName())&&this.age==p.getAge()){
                return true;
            }
        }
        return false;
    }
    @Override
    public int hashCode() {				//重写hashCode
        final int prime=31;       //使用31的原因:31是个质数,减少散列冲突;提高执行效率,i*31是将左移5位再减i 即31*i=(i<<5)-i
        int result=1;
        result=prime*result+age;
        result=prime*result+((name==null) ? 0:name.hashCode());
        return result;
    }
    //重写后比较规则:先按姓名比,再按年龄比
    public int compareTo(Person o) {
        int n1=this.getName().compareTo(o.getName());
        int n2=this.age-o.getAge();
        return n1==0?n2:n1;         //如果n1=0,即两个名字相等,那么返回n2,否则返回n1
    }
}
//===================================================================
/*
 * TresSet的使用  复制类型
 *存储结构:红黑树
 *要求:元素必须要实现Comparable接口
 * */
public class Demo05 {
    public static void main(String[] args) {
        //创建集合
        TreeSet<Person> people = new TreeSet<Person>();
        Person p1 = new Person("angle",3);
        Person p2 = new Person("jack",2);
        Person p3 = new Person("marry",5);
        Person p4 = new Person("marry",1);
        Person p5 = new Person("jhon",4);
        people.add(p1);             //如果实体类没有实现Comparable接口并重写compareTo方法,会报类型转换异常(无法比较进而排序)
        people.add(p2);
        people.add(p3);
        people.add(p4);
        people.add(p5);
        System.out.println(people);
        
        //遍历    增强for和迭代iterator
        for (Person person : people) {
            System.out.println(people);
        }
        
        //判断
        System.out.println(people.contains(p3));

        //删除
        people.remove(p1);
        people.remove(new Person("jhon",4));        //重写过equals方法和hashCode方法,所以此处可以实现
        System.out.println(people);
    }
}
/*
* TreeSet集合的使用
* Comparator:实现定制比较(比较器)  在创建集合是指定比较规则,实体类可以不用实现Comparable接口
* Comparable:可比较的
* */
public class Demo06 {
    public static void main(String[] args) {
        //创建集合,并指定比较规则 通过接口实现类的匿名内部类方式
        TreeSet<Person> people = new TreeSet<Person>(new Comparator<Person>() {		//此时实体类可以不用实现Comparable接口 
            public int compare(Person o1, Person o2) {
                int n1=o1.getAge()-o2.getAge();
                int n2=o1.getName().compareTo(o2.getName());
                return n1==n2?n2:n1;
            }
        });

        Person p1 = new Person("angle",3);
        Person p2 = new Person("jack",2);
        Person p3 = new Person("marry",5);
        people.add(p1);
        people.add(p2);
        people.add(p3);

        System.out.println(people);

    }
}

Map接口与实现类

**Map接口特点:**键值对,无序、无下标,键不可重复,值可重复

  • 用于存储任意键值对(key- Value)
  • 键:无序、无下标、不允许重复(唯一)
  • 值:无序、无下标、允许重复

方法:

  • V put(K key,V value) 将对象存入到集合中,关联键值。key重复则覆盖原value值
  • Object get(Object key) 根据键获取对应的值
  • Set 返回所有的key
  • Collection values() 返回包含所有值的Collection集合
Map接口基本使用示例
/*
* Map接口的使用
* 特点:1.储存键值对  2.键不能重复,值可以重复  3.无序
* */
public class Demo01 {
    public static void main(String[] args) {
        //创建Map集合
        Map<String,String> map=new HashMap<String, String>();
        //添加元素    put方法
        map.put("BJ","北京");
        map.put("SH","上海");
        map.put("WH","武汉");
        map.put("SZ","深圳");
        map.put("SZ","shenzhen");           //key重复,后面添加的  shenzhen  将前面添加的  深圳  替换掉了
        map.put("首都","北京");             //key不重复,值重复,可以添加进来
        System.out.println(map.size());
        System.out.println(map);            //{WH=武汉, SH=上海, SZ=深圳, BJ=北京}   无序

        //遍历
        //方法1.keySet(),返回值是所有key的Set集合,要获取值还需要调用map的get()方法  get()方法是通过key获取value
        System.out.println("---keySet()方法遍历---");
        for (String key : map.keySet()) {
            System.out.println(key+"---"+map.get(key));
        }

        //方式2.entrySet(),返回值类型Entry是键值对      该方法可直接获取键与值
        System.out.println("---entrySet()方法遍历---");
        for (Map.Entry<String, String> entry : map.entrySet()) {
            System.out.println(entry);
        }

        //判断
        System.out.println(map.containsKey("SZ"));      //判断是否存在某个key
        System.out.println(map.containsValue("上海"));    //判断是否存在某个value

        //删除
        map.remove("首都");
        System.out.println(map);
    }
}

Map集合的实现类

  • HashMap【重点】
    • JDK1.2版本出现,线程不安全,运行效率快:允许null作为key或者value
    • 默认初始容量是16,加载因子是0.75(超过总容量75%是开始扩容)
    • 方法同Map集合
  • HashTable
    • 实现一个哈希表,该哈希表将键映射到相应的值
    • JDK1.0出现,线程安全,运行效率慢;不允许null左右键或者值
    • 现在几乎不用
    • Properties是HashTable的子类(使用相对较多)
      • 要求key和value都是String,常用于配置文件的读取
      • 与流联系较多
  • TreeMap
    • 数据结构是红黑树
    • 实现了SortedMap接口(是Map的子接口),可以对key进行自动排序
HashMap集合的使用
/*
* HashMap集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
* */
//===============================================实体类
public class Student {
    private String name;
    private int id;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", id=" + id +
                '}';
    }
}
//======================================================HashMap集合
public class Demo02 {
    public static void main(String[] args) {
        //创建集合
        HashMap<Student, String> hashMap = new HashMap<Student, String>();
        Student s1 = new Student("果果", 1);
        Student s2 = new Student("欢欢", 2);
        Student s3 = new Student("乐乐", 3);
        Student s4 = new Student("小黑", 4);
        hashMap.put(s1,"白色");
        hashMap.put(s2,"棕色");
        hashMap.put(s3,"花白");
        hashMap.put(s4,"黑色");
        hashMap.put(s4,"黄色");                       //重复输入键值相同的,会将前面的旧数据覆盖
        hashMap.put(new Student("小虎",5),"灰白色");
        System.out.println(hashMap);                //打印结果看是无序的

        //遍历  keySet()方法    entrySet()方法
        System.out.println("keySet()遍历-----");
        for (Student student : hashMap.keySet()) {
            System.out.println(student);
        }

        System.out.println("entrySet()遍历****");
        for (Map.Entry<Student, String> stu : hashMap.entrySet()) {
            System.out.println(stu);
        }

        //判断
        System.out.println(hashMap.containsKey(s3));
        System.out.println(hashMap.containsValue("黄色"));

        //删除
        hashMap.remove(s1);
    }
}

HashMap小结:

    • HsahMap刚创建时,table是null,是为了节省空间,当添加第一个元素时,table容量调整为16
    • 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍;目的是减少调整元素的个数
    • jdk1.8 当每个链表长度大于8,并且数组元素大于等于64时,会调整为红黑树,目的是提高执行效率
    • jdk1.8 当链表长度小于6时,调整成链表
    • jdk1.8 以前,链表是头插入,jdk1.8 以后是尾插入
TreeMap集合使用
/*
*TreeMap集合的使用
*储存结构:红黑树
* */
//======================================================实体类
public class Student implements Comparable<Student>{
    private String name;
    private int id;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

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

    public int compareTo(Student o) {			//重写compareTo方法
        int n=this.id-o.getId();
        return n;
    }
}
//===================================================================
public class Demo3 {
    public static void main(String[] args) {
        //创建集合
        TreeMap<Student, String> treeMap = new TreeMap<Student, String>();
        Student s1 = new Student("果果", 1);
        Student s2 = new Student("欢欢", 2);
        Student s3 = new Student("乐乐", 3);
        Student s4 = new Student("小黑", 4);
        treeMap.put(s1,"白色");
        treeMap.put(s2,"棕色");
        treeMap.put(s3,"花白色");
        treeMap.put(s4,"黑色");
        System.out.println(treeMap);        //直接将复杂对象Student类作为key传入,会导致类型转换异常
                                            //需要Student类实现Comparable接口,并重写compareTo方法
											//或者在创建集合的时候使用定制比较器,用用匿名内部类的方法
        //遍历      keySet()方法  entrySet()方法
        System.out.println("keySet()---");
        for (Student student : treeMap.keySet()) {
            System.out.println(student);
        }

        System.out.println("entrySet()***");
        for (Map.Entry<Student, String> entry : treeMap.entrySet()) {
            System.out.println(entry);
        }

        //判断
        treeMap.containsKey(s4);

        //删除
        treeMap.remove(s3);
    }
}

Collections工具类

  • 概念:集合工具类,定义了除了存取意外的集合常用方法
  • 方法:
    • public static void reverse(List<?> list) 反转集合中元素的顺序
    • public static void shuffle(List<?> list) 随机重置集合元素的顺序
    • public static void sort(List list) 升序排序(元素必须实现Comparable接口)
public class Demo04 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(20);
        list.add(6);
        list.add(25);
        list.add(2);
        list.add(44);
        list.add(8);
        System.out.println("排序前"+list);     //排序前[20, 6, 25, 2, 44, 8]
        //sort  排序
        Collections.sort(list);
        System.out.println("排序后"+list);     //排序后[2, 6, 8, 20, 25, 44]
        //reverse 反转
        Collections.reverse(list);
        System.out.println("反转后"+list);     //反转后[44, 25, 20, 8, 6, 2]
        
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值