JavaSEday08List、Set、数据结构和Collections

第8天_面向对象(List、Set、数据结构、Collections)
    一.数据结构
        1.什么是数据结构
            容器中存放组织数据的一种结构
        2.常见的4+1中数据结构
            堆栈结构
                可以看作只有一端开口的容器,先进后出(FILO)
            队列结构
                可以看成两端开口的容器。一端进,一端出,先进先出(FIFO)
            数组结构
                在内存中是一块连续的区域,查询快(通过索引),增删慢(长度固定)。(垃圾回收机制)
            链表结构
                在内存中可以分散,链表中的元素我们一般成为节点,一般有两个属性,数据域和指针域
                查询慢,增删快
            红黑树结构
                查询速度非常恐怖O(log(n))
                增删速度包括创建时都是非常慢的            
            哈希表结构底层就是数组和链表,jdk8之后加入红黑树优化。
    二.List接口
        1.List接口的特点
            a.有序的collection(也成为序列)。
            b.有索引
            c.元素可重复
        API的描述:
            有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

        2.List接口中常用的方法以及常用实现类
            a.拥有Collection接口中的方法和迭代器
            b.还有四个和索引相关的增删改查方法
                public void add(int index, E e):插入元素
                public E remove(int index):根据索引删除元素
                public E set(int index, E e):修改指定索引的元素
                public E get(int index):根据索引获取元素
            c.List接口的实现类
                ArrayList
                LinkedList
                Vector
        3.ArrayList的数据结构以及使用
            ArrayList底层是数组结构,特点是查询快,增删慢!!!
            特有方法:无    
        4.LinkedList的数据结构以及使用
            LinkedList底层是链表结构,特点是查询慢,增删快!!!
            特有方法(8个):8个和首尾操作相关的方法
                public void addFirst(E e):添加首
                public void addLast(E e):添加尾

                public E removeFirst():删除首
                public E removeLast():删除尾

                public E getFirst():返回首
                public E getLast():返回尾                public E pop():删除首,就是跟removeFirst一样的
                public void push(E e):添加首,就是跟addFirst一样的
                addFirst和removeFirst是1.2就有的,java是1.5开始火的,这两个方法是jdk1.6之后添加的,商业需要,为了吸引更多的开发者(别的语言中增添方法名就是push和pop)

public class TestLinkedList {
    public static void main(String[] args) {
        //1.创建一个LinkedList
        LinkedList<String> list = new LinkedList<String>();
        //2.添加首尾
        list.addLast("刘岩");
        list.addFirst("贾乃亮");
        list.addLast("蔡徐坤");
        list.addFirst("马蓉");
        list.addLast("王宝强");
        list.addFirst("宋吉吉");
        list.addLast("李小璐");
        list.addFirst("PGOne");
        //3.打印
        //"PGOne" "宋吉吉" "马蓉" "贾乃亮" "刘岩" "蔡徐坤" 王宝强" "李小璐"
        System.out.println(list);
        //3.删除首尾
        String first = list.removeFirst();
        System.out.println(first);
        System.out.println(list);

        String last = list.removeLast();
        System.out.println(last);
        System.out.println(list);
        //[宋吉吉, 马蓉, 贾乃亮, 刘岩, 蔡徐坤, 王宝强]
        //4.获取首尾
        String first1 = list.getFirst();
        System.out.println(first1);
        System.out.println(list);

        String last1 = list.getLast();
        System.out.println(last1);
        System.out.println(list);
        //[宋吉吉, 马蓉, 贾乃亮, 刘岩, 蔡徐坤, 王宝强]
        //5.push和pop
        list.push("666");
        System.out.println(list);

        String pop = list.pop();
        System.out.println(pop);
        System.out.println(list);
    }
}        

    三.Set接口
        1.Set接口的特点
            a.无序的(是指存的和取的顺序是不一定一致的,LinkedHashSet除外,它是有序的)
            b.无索引
            c.元素唯一
        2.Set接口的常用方法以及常用子类
            a.拥有Collection接口中的方法和迭代器
            b.特有方法:无
            c.Set接口常见的实现类
                HashSet(无序)
                    LinkedHashSet(有序)
                TreeSet

        3.HashSet的数据结构以及使用
            HashSet底层采用哈希表结构
            特有方法:无

public class TestHashSet {
    public static void main(String[] args) {
        //1.创建一个HashSet
        HashSet<String> set = new HashSet<String>();
        //2.添加
        set.add("jack");
        set.add("jack");
        set.add("jack");
        set.add("rose");
        set.add("rose");
        set.add("lilei");
        set.add("hanmeimei");
        set.add("hanmeimei");
        set.add("lucy");
        set.add("lucy");
        set.add("lucy");
        System.out.println(set);
        //[lilei, hanmeimei, rose, lucy, jack]
    }
}


        

        4.哈希表结构的介绍[扩展]
            哈希表结构 = 数组(默认长度16) + 链表 + 红黑树(jdk1.8)
            i.对象的哈希值(对象的“数字指纹”)
                我们怎么获取到对象的哈希值?
                    只要调用对象的hashCode方法即可获取到对象的哈希值
                Java中的地址值是假的!而是哈希值转成了16进制而已

                Java中有没有真正的地址值?
                    有!!!对象名中保存就是真正的地址值
                    但是我们打印不出来,因为我们打印对象名的时候,会默认调用toString方法,屏蔽了真正的地址值,是一                    种内存保护机制,因此Java的安全性很高
                public String toString() {
                        return getClass().getName() + "@" + Integer.toHexString(hashCode());
                }//返回值为包名.类名@hashCode的十六进制值

                不同对象的Hash值可能一样的
                    "abc"和"acD"都是96354(hashCode方法在String类重写了)
*************结论:哈希表结构如何保证元素的唯一性??***************
        哈希表会比较新旧元素的哈希值,以及调用equals方法,
        只有哈希值一致的情况下,并且equals返回true,才判定元素重复
*******************************************************************
        注意:桶的长度为8,当桶中的元素超过8时,结构自动变成红黑树
            

        5.LinkedHashSet的数据结构以及使用
            LinkedHashSet底层采用链式哈希表
            特有方法:无

public class TestLinkedHashSet {
    public static void main(String[] args) {
        //1.创建一个HashSet
        LinkedHashSet<String> set = new LinkedHashSet<String>();
        //2.添加
        set.add("lucy");
        set.add("hanmeimei");
        set.add("rose");
        set.add("rose");
        set.add("rose");
        set.add("lilei");
        set.add("jack");
        System.out.println(set);
        //[lucy, hanmeimei, rose, lilei, jack]
    }
}


        练习:使用哈希表结构保存自定义类型的元素******************
******************************************************************************
    使用哈希表结构保存自定义类型时,
    为了保证元素是唯一,需要重写自定义类型中的hashCode和equals方法(工具自动生成)
******************************************************************************

public class Cat {
    int age;
    String name;
    public Cat() {
    }
    public Cat(int age, String name) {
        this.age = age;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Cat{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
    //为了保证元素的唯一性,自定义类型必须重写hashCode和equals方法
    //alt+insert
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Cat cat = (Cat) o;
        return age == cat.age &&
                Objects.equals(name, cat.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(age, name);
    }
}


//练习:使用哈希表结构保存自定义类型的元素*********************

public class HashCodeTestDemo {
    public static void main(String[] args) {
        //1.LinkedHashSet
        LinkedHashSet<Cat> cats = new LinkedHashSet<Cat>();
        //2.保存猫
        cats.add(new Cat(1, "小猫咪"));
        cats.add(new Cat(2, "中猫咪"));
        cats.add(new Cat(3, "大猫咪"));
        cats.add(new Cat(3, "大猫咪"));
        cats.add(new Cat(4, "老猫咪"));
        cats.add(new Cat(5, "死猫咪"));
        //3.打印
        System.out.println(cats);
    }
}


        6.可变参数
            可变参数是指参数的个数可以变化
            格式:
                数据类型... 变量名
            本质:
                实际上可变参数就是数组(语法糖)
            注意:
                a.一个方法最多只能有一个可变参数
                b.如果既有可变参数,也有正常参数,正常参数要写在可变参数的前面

public class TestDemo {
    public static void main(String[] args) {
        //调用方法
        System.out.println(getSum());
        System.out.println(getSum(1));
        System.out.println(getSum(1, 2));
        System.out.println(getSum(1, 2, 3, 4, 5, 6, 7, 8, 9,10));
    }
    //使用可变参数
    public static int getSum(int... a) {
        //数组求和
        int sum = 0;
        for (int i : a) {
            sum+=i;
        }
        return sum;
    }
}


    四.Collections
        1.Collections的介绍
            Collections是一个工具类(方法都是静态的)
        2.常用功能方法
            public static void shuffle(List<?> list):打乱集合顺序
            public static void sort(List<?> list):升序排列集合

public class CollectionsDemo01 {
    public static void main(String[] args) {
        //1.sort方法
        ArrayList<Integer> nums = new ArrayList<Integer>();
        //2.数据
        nums.add(80);
        nums.add(20);
        nums.add(70);
        nums.add(40);
        nums.add(10);
        nums.add(50);
        nums.add(100);
        nums.add(60);
        nums.add(30);
        nums.add(90);
        //3.打印
        System.out.println(nums);
        //4.排序
        Collections.sort(nums);
        //5.打印
        System.out.println(nums);
    }
}


            关于sort方法的排序规则:
                如果元素是数值类型,按照大小升序
                如果元素是字符类型,按照ASCII码值升序
                如果元素是字符串类型,首先按照首字母的ASCII码值升序,首字母一样按照次字母ASCII码值升序,依次类推
        3.扩展1:Comparator<T>比较器接口******************

public class CollectionsDemo02 {
    public static void main(String[] args) {
        //1.sort方法
        ArrayList<Integer> nums = new ArrayList<Integer>();
        //2.数据
        nums.add(80);
        nums.add(20);
        nums.add(70);
        nums.add(40);
        nums.add(10);
        nums.add(50);
        nums.add(100);
        nums.add(60);
        nums.add(30);
        nums.add(90);

        //4.排序
        Collections.sort(nums,new Comparator<Integer>(){
            //此方法称为比较方法
            //返回值表示
            //正数  表示前者大于后者
            //0  表示前者等于后者
            //负数 表示前者小于后者
            @Override
            public int compare(Integer o1, Integer o2) {
                //升序 前-后
//                return o1-o2;
                return o2-o1;
            }
        });
        //5.打印
        System.out.println(nums);
    }
}

4.排序练习(代码实现)

/**
 * 使用集合保存学生对象,对集合进行排序
 */
public class CollectionsDemo03 {
    public static void main(String[] args) {
        //1.创建一个ArrayList
        ArrayList<Student> ss = new ArrayList<Student>();
        //2.添加学生
        ss.add(new Student(20,"haneimei",50));
        ss.add(new Student(10,"jack",90));
        ss.add(new Student(8,"ady",95));
        ss.add(new Student(9,"tonny",100));
        ss.add(new Student(25,"yy",30));
        //3.遍历
        for (Student s : ss) {
            System.out.println(s);
        }
        System.out.println("===========================");
        Collections.sort(ss, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
               //口诀:升序 前减后
                //a.按照年龄降序
//                return o2.age-o1.age;
                //b.按照分数升序
//                return o1.score-o2.score;
                //c.按照名字的长度降序
//                return o2.name.length()-o1.name.length();
                //d.按照姓名的第二个字母降序
                return o2.name.charAt(1)-o1.name.charAt(1);
            }
        });

        for (Student s : ss) {
            System.out.println(s);
        }
    }
}


总结:
    -[] 能够说出List集合特点
            有序,有索引,可重复
    -[] 能够说出常见的数据结构
    -[] 能够说出常见的数据结构
    -[] 能够说出数组结构特点
    -[] 能够说出栈结构特点
    -[] 能够说出队列结构特点
    -[] 能够说出单向链表结构特点
    -[] 能够说出Set集合的特点
            无序,无索引,唯一
    -[] 能够说出哈希表的特点
            哈希表中的元素是唯一的
            哈希表通过哈希值和equals共同保证元素的唯一性
    -[] 使用HashSet/LinkedHashSet集合存储自定义元素
            自定义类型需要重写hashCode和equals
    -[] 能够使用集合工具类的常用方法
            public static void shuffle(List<?> list):打乱集合顺序
            public staitc void sort(List<?> list):升序排序集合    -[] 能够使用Comparator比较器进行排序
            

Collections.sort(集合<E>, new Comparator<E>{
                public int compare(E e1, E e2){
                    升序 前减后
                }
            });

    


        
            

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章