day03【List接口、Set接口、Collections工具类】

数据结构:

互相之间存在一种或多种特定关系的数据的集合。

栈(Stack):也叫做“堆栈”。特点:先进后出。

队列(Queue):先进来的先出去,后进来的后进去。先进先出。

数组(Array):内存空间是连续的。特点:查找快,增删慢(会创建一个新数组接收增删后的元素)。

链表(Linked List):内存空间不连续的。特点:增删快,查找慢。

单项链表:每个元素都知道下一个元素的地址。

双向链表:前一个元素知道下一个元素的地址,后一元素也知道前一个元素的地址。

树:

二叉树:

排序树:在二叉树的基础上,左边都小于右边。

平衡树:左右两边对称

红黑树的数学约束

1、结点可以是红色或者是黑色。

2、根节点是黑色。

3、叶子结点(特指空节点)是黑色。

4、每个红色节点的子节点必须是黑色。

5、任何一个节点到其每一个叶子节点的所有路径上黑色节点数量相同。

红黑树的特点:速度特别快。

查找速度特别快,趋近于平衡排序儿二叉查找树。

查找叶子节点的步骤,最多和最少不超过二倍的关系。

List

java.util.List是Collection接口的子接口,特点:

1、可以存储重复元素。

2、有先后顺序。

3、有索引值。

常用的实现类有

1、ArrayList:底层使用的是数组。查找快,增删慢。

2、LinkedList:底层使用的是链表。增删快,查找慢。

3、Vector:底层使用的也是数组,和ArrayList基本一样,不过线程安全。

Collection接口的方法,List都有。

List特有方法

public void add(int index , E element): 添加一个元素到指定的索引位置。
public E remove(int index):根据指定索引值删除一个元素,返回被删除的元素。
public E set(int index, E replacemrnt):根据指定索引值替换一个元素,返回被替换的元素。
public E remove(int index):根据指定索引值删除一个元素,返回被删除的元素。
public E get(int index):根据指定索引值获取一个元素。

增删改查:CRUD Create Read Update Delete

List<String> list = new ArrayList<>();
list.add("张小凡");
list.add("张无忌");
list.add("张三丰");
list.add("宋青书");
System.out.println(list); // 有顺序 [张小凡, 张无忌, 张三丰, 宋青书]

list.remove("张三丰"); // 删除张三丰
System.out.println(list); // [张小凡, 张无忌, 宋青书]

// list.remove(3); //
// IndexOutOfBoundsException: 由于删除张三丰后,只剩下三个值,索引最大为2,删除3不存在
// System.out.println(list); 

list.set(1,"赵敏"); // 修改索引1
System.out.println(list); // [张小凡, 赵敏, 宋青书]

list.remove(0); // 删除索引值为0的对象
System.out.println(list); // [赵敏, 宋青书]

// 获取索引值为0的对象
System.out.println(list.get(0)); // 赵敏

LinkedList当中特有的方法:

public void addFirst(E e):在开头添加一个元素。
public void addLast(E e):在末尾添加一个元素。
public E getFirst(): 获取开头的元素。
public E getLast(): 获取末尾的元素。
public E removeFirst(): 删除开头元素。
public E removeLast(): 删除末尾的元素。

        LinkedList<String> list = new LinkedList<>();
        list.add("张小凡");
        list.add("张无忌");
        list.add("张三丰");
        list.add("宋青书");
        System.out.println(list); // [张小凡, 张无忌, 张三丰, 宋青书]

        list.addFirst("赵敏"); // // 新加入的元素加在原来集合的最前
        System.out.println(list); // [赵敏, 张小凡, 张无忌, 张三丰, 宋青书]

        list.addLast("李白"); // 新加入的元素加在原来集合的最后
        System.out.println(list); // [赵敏, 张小凡, 张无忌, 张三丰, 宋青书, 李白]

        list.removeFirst(); // 删除开头元素
        System.out.println(list); // [张小凡, 张无忌, 张三丰, 宋青书, 李白]

        list.removeLast(); // 删除最后一个元素
        System.out.println(list); // [张小凡, 张无忌, 张三丰, 宋青书]

        // 获取开头元素
        System.out.println(list.getFirst()); // 张小凡
        // 获取末尾元素
        System.out.println(list.getLast()); // 宋青书

注意:

如果集合中没有元素了,接着删除,会报没有元素异常错误。

LinkedList当中有两个与栈相关的方法:

public void push(E e): 压栈、进栈,在左边添加一个元素。相当于addFirst方法。
public E pop(): 弹栈、出栈,在左边删除并去除一个元素。相当于removeFirst方法。

对于这两个方法来说,数据元素的出入口全都是左边。

        LinkedList<String> list = new LinkedList<>();
        list.add("张小凡");
        list.add("张无忌");
        list.add("张三丰");
        list.add("宋青书");
        System.out.println(list); // [张小凡, 张无忌, 张三丰, 宋青书]

        list.push("范冰冰"); // 把范冰冰压进栈,在最左端加入一个新元素,相当于addFirst
        System.out.println(list); // [范冰冰, 张小凡, 张无忌, 张三丰, 宋青书]

        list.pop(); // 出栈,把最左端的元素删除,相当于removeFirst
        System.out.println(list); // [张小凡, 张无忌, 张三丰, 宋青书]

Set

java.util.Set是Collection的子接口。特点:

1、不允许重复元素

2、不保证先后顺序

3、没有索引值

常用子类:

1、HashSet:速度特别快,不保证顺序

2、LinkedHashSet:速度也很快,但是还能额外保证顺序。

3、TreeSet:有大小排序功能

注意:先后顺序和大小排序是不一样的。

HashSet集合是最常用的Set集合,特点:

因为底层使用了一种名叫“哈希表”的数据结构,所有查找元素的速度特别快。

底层原理其实是在复用HashMap。

重点:

HashSet是如何判断元素是否重复的?如何得知集合当中是否已经存在了重复的元素?

两个对象是否相同,由equlas和hashCode两个方法共同决定。

public int hashCode():根据当前对象那个,产生一个“哈希值”(对象的特征码)。

如果没有覆盖重写hashCode方法,那么Object当中的hashCode将会在JVM当中:

默认使用对象的内存地址值参与运算,然后得到一个与地址相关的int数字:哈希值。

只要内存够用,可以创建很多个对象,无数个不同的地址值。

默认的哈希值只是使用了地址值参与运算而已,并不直接等于地址值。

无数种地址–> 哈希运算hashCode()–>42亿种int哈希值。

意味着: 可能有不一样的对象,哈希值是相同的。

哈希原理:先分类,再查找。

哈希表: 本身就是一个数组,默认长度为16。

桶(Bucket):就是哈希表数组当中的一个小格。

哈希冲突:不一样的对象被放在了同一个桶当中。

加载因子: 就是一个百分比,默认0.75,一旦哈希表当中已经被占用的桶,占用了总桶的个数超过了加载因子的比例,那么哈希表将会自动扩容。

再哈希(rehash):达到加载因子之后,哈希表进行重新更加细致地分类。

在java7之前,就是单纯的链表。

在java8以及之后,将会在长度达到8之后,自动从链表变身成为红黑树。

红黑树的特点:快。

HsahSet是如何确定元素是否重复?(这就是一个对象查找的过程)

1、如果hashCode不一样,那么两个对象肯定不一样。(姓张的和姓李的,肯定不是一个人。)

2、如果hashCode一样,但是equals不一样,那么两个对象就不一样。

3、如果hashCode一样,并且equals也一样,那么两个对象才一样。

hashCode方法的三条原则:

1、运行期一致性。

2、对象相同,那么哈希值必须相同。

3、对象不同,那么哈希值不一定相同。

equals方法的五条原则

1、自反性:自己和自己比较,一定相同。

2、对称性:A比较B,B比较A,效果一样。

3、传递性:如果AB一样,并且BC一样,那么AC也一样。

4、一致性:只要对象的内容不变,比较的结果就不能变。

5、无非空:任何对象和null值比较,一定是false。

如果在哈希结构当中存储自定义的类型,那么必须覆盖重写equals和hashCode方法。

        Set<String> list = new HashSet<>();
        list.add("AAA");
        list.add("BBB");
        list.add("CCC");
        list.add("DDD");
        // 打印出来的元素,1、没有顺序,2、没有索引值,3、不允许重复元素
        System.out.println(list); // [张小凡, 宋青书, 张三丰, 张无忌]

        // 添加一个集合中已经存在的元素
        boolean b = list.add("张小凡");
        System.out.println(b); // false

        Iterator<String> iter = list.iterator();
        while (iter.hasNext()) {
            System.out.println(iter.next()); // 无序
        }
        System.out.println("====================");

        Set<String> linkSet = new LinkedHashSet<>();
        linkSet.add("AAA");
        linkSet.add("BBB");
        linkSet.add("CCC");
        linkSet.add("DDD");
        for (String s : linkSet) {
            System.out.println(s); // 升序排列
        }

LinkedHashSet是HashSet的子类:

额外添加了一层双向链表,咱们用来维护顺序。

可变参数就是参数的类型统一,但是个数随意。java5添加的特性之一

格式:

修饰符 返回值类型 方法名称(参数类型... 参数名称){
    //方法体
}

注意事项:

1、可变参数只是一个语法糖,底层其实就是普通的数组。

2、方法的可变参数只能有一个。

3、方法的可变参数只能是最后一个。

    public static void main(String[] args) {

        long result = push(10, 20, 30);
        System.out.println(result); // 60

    }

    private static int push(int... nums) {
        int num = 0;
        for (int i = 0; i < nums.length; i++) {
            num += nums[i];
        }
        return num;
    }

Collections

是与集合相关的工具类,其中有常用的静态方法:

public static void shuffle(List<?> list):打乱集合当中的顺序。
public static boolean addAll(Collection c,T... elements):第一个参数代表加到那个集合中,第二个可变参数代表需要添加的元素都有谁。
public static void sort(List list): 按照自然顺序进行大小排序。
public static void sort(List list, Comparator comp): 第二个参数代表排序的规则。

        List<String> list = new ArrayList<>();
        list.add("AAA");
        list.add("BBB");
        list.add("CCC");
        list.add("DDD");
        System.out.println(list);

        Collections.shuffle(list); // 将list设置成随机顺序
        System.out.println(list); // [CCC, DDD, AAA, BBB]

        Collections.addAll(list,"FFF","GGG");
        System.out.println(list); // [BBB, CCC, AAA, DDD, FFF, GGG]

1、对Comparable来说:升序就是我减他。

2、对Comparator来说:升序就是1-2。

// 测试类
List<Person> p = new ArrayList<>();
p.add(new Person("鹿晗",30));
p.add(new Person("吴亦凡",40));
p.add(new Person("张艺兴",20));

// 对象类必须去实现Comparable才能使用
Collections.sort(p);
// [Person{name='张艺兴', age=20}, Person{name='鹿晗', age=30}, Person{name='吴亦凡', age=40}]
System.out.println(p);

// Person类:

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;
    }

    @Override
    public int compareTo(Person o) {
        // 升序就是我减他
        return age - o.age;
    }
....

    public static void main(String[] args) {
        List<Person> p = new ArrayList<>();
        p.add(new Person("鹿晗", 30));
        p.add(new Person("吴亦凡", 40));
        p.add(new Person("张艺兴", 20));

        // 采用匿名内部类的方法调用Comparator
        Collections.sort(p, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge(); // 年龄升序
            }
        });
        // [Person{name='张艺兴', age=20}, Person{name='鹿晗', age=30}, Person{name='吴亦凡', age=40}]
        System.out.println(p); // 年龄升序排列

        // 扩展一丢丢:
        Collections.sort(p, (a, b) -> a.getAge() - b.getAge()); // day07学习的Lambda表达式
        Collections.sort(p, Comparator.comparingInt(Person::getAge)); // day13学习之后扩展的第五种方法引用

    }
}

栈图
这里写图片描述
队列
这里写图片描述
数组
这里写图片描述
链表
这里写图片描述
红黑树
这里写图片描述
哈希表存储原理
这里写图片描述
HashSet查找元素的过程
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值