黑马程序员技术交流社区

标题: 11/15日day03-List-Set [打印本页]

作者: 849618121    时间: 2018-11-26 15:03
标题: 11/15日day03-List-Set
day03 List Set 今日内容
数据结构
集合
        List集合
        Set集合
Collections集合工具类
数据结构
数据结构: 就是数据的存储方式
        不同的数据结构代表了不同的存储方式
        不同的数据结构中, 会有不同的存入, 取出, 查找的方式和效率, 数据的存放方式也不同
       
        如薯片, 可以用长纸筒装, 也可以用塑料包装袋装, 在两种容器中的存储方式就不同, 放入和取出的方式也不一样![](./img/薯片的数据结构.JPG) 栈知识点:
栈结构存入和取出数据的顺序有什么特点
栈结构适用于什么场景
总结:
栈:
    ^  |
    |  v
|             |  出入口在同一端
| +---------+ |
| |    3    | |
| +---------+ |
| +---------+ |
| |    2    | |   栈
| +---------+ |
| +---------+ |
| |    1    | |
| +---------+ |
+-------------+
栈的特点:
        先进后出 (FILO, First In Last Out)
        入口和出口在同一侧
       
入栈(压栈): 将元素存入栈
出栈(弹栈): 从栈中取出元素栈的适用场景:
        栈内存 (main方法先进栈调用, main方法中的其他方法都调用完毕后, main才能出栈)
        反转内容 (车尾变车头, 进去再出来就反转了)
补充: 队列知识点:
队列结构存入和取出数据的顺序有什么特点
队列结构适用于什么场景
总结:
队列:入口                                                  出口
   -----------------------------------------------
        +---------+ +---------+ +---------+
---->       |   3   | |   2   | |   1   |  ---->
        +---------+ +---------+ +---------+
   -----------------------------------------------
队列的特点:
        先进先出 (FIFO, First In First Out)
    入口和出口在两端
   
队列的适用场景:
        秒杀, 抢购
        在线售票
        处理高并发场景![](./img/队列的应用.png)补充: 数组知识点:
数组结构增删和查询数据有什么特点
数组结构适用于什么场景
总结:
数组:
        0x01  0x02  0x03  0x04  0x05
        +-----+-----+-----+-----+-----+
        | "a" | "b" | "c" | "d" | "e" |
        +-----+-----+-----+-----+-----+
                0   1                   2   3           4
        
数组的特点:
        查询快: 通过 (第一个元素地址值 + 索引) 可以快速计算出该索引元素的地址值
        增删慢: 增加一个元素, 要创建长度+1的新数组, 然后将原数组元素复制到新数组, 然后存入新元素; 删除类似
       
        // 添加元素
        +-----+-----+-----+-----+-----+
        | "a" | "b" | "c" | "d" | "e" |   如果要添加元素"f"
        +-----+-----+-----+-----+-----+
        
        +-----+-----+-----+-----+-----+-----+
        | "a" | "b" | "c" | "d" | "e" | "f" |  创建一个新数组, 将原数组元素复制进去, 然后存入新元素
        +-----+-----+-----+-----+-----+-----+
       
数组的适用场景:
        查询多, 增删少的数据存储场景   国内城市![](./img/变量数组在内存中的体现.png)补充: 链表知识点:
链表结构增删和查询数据有什么特点
链表由什么组成
什么是单向链表
什么是双向链表
链表结构适用于什么场景
总结:
链表: 链表由多个 节点(Node / Entry) 组成
        +-----+-----+-----+    +-----+-----+
        |     |     |     |    |数据  |     |
        +-----+-----+-----+    +-----+-----+   
单向链表: 每个节点存储 数据 和 下一个节点的地址值        链表 = 0x11;        0x11              0x44              0x88
        +-----+-----+     +-----+-----+     +-----+-----+
        | "a" | 0x44| --> | "b" | 0x88| --> | "c" | null|
        +-----+-----+     +-----+-----+     +-----+-----+
      数据  下一个        数据  下一个       数据  下一个
双向链表: 每个节点存储 数据, 上一个节点地址值 和 下一个节点地址值
        0x11                    0x44                      0x88
        +-----+-----+-----+      +-----+-----+-----+      +-----+-----+-----+
        |null | "a" | 0x44| <--> |0x11 | "b" | 0x88| <--> |0x44 | "c" | null|
        +-----+-----+-----+      +-----+-----+-----+      +-----+-----+-----+
     上一个  数据  下一个        上一个  数据  下一个        上一个  数据  下一个
链表的特点:
        查询慢: 要找到其中某个节点, 只能从第一个节点一个一个向后寻找
        增删快: 只需要修改保存的下一个节点的地址值, 就可以快速完成增删
       
        // 删除结点
        +---+           +---+   +---+
        | 1 |----| 2 |----| 3 |
        +---+           +---+   +---+
        +---+                      +---+
        | 1 |-------------| 3 |
        +---+                        +---+
                            +---+
                            | 2 |
                            +---+
       
链表的适用场景:
        查询少, 增删多的场景
        链表可以实现栈和队列的结构, 因为栈和队列增删频繁
补充:
代码中链表节点的实现:// 单向链表的节点
class Node<T> {
        T data;       // 存储的数据
        Node next;    // 下一个节点的地址值
}// 双向链表的节点
class Node<T> {
        T data;       // 存储的数据
        Node before;  // 上一个节点的地址值
        Node after;   // 下一个节点的地址值
}
红黑树知识点:
红黑树结构有什么特点
红黑树结构适用于什么场景
总结:
红黑树: 是一种 平衡 二叉 查找 树
        平衡: 左子节点和右子节点数量相等
        二叉: 每个节点最多有2个子节点
        查找: 节点存储的元素是按照大小顺序存储的
        特点:
                元素存储过程中就完成了大小排序
                查询比链表快, 增删比数组快 (数组和链表的折中)红黑树的适用场景:
        查询和增删都有, 需要元素自动排序的场景![](./img/04_数据结构_红黑树.bmp)树的遍历:![](./img/树的遍历.gif)补充:
代码中树节点的实现// 树的节点
class Entry<T> {
        T data;           // 存储的数据
        Entry left;       // 左子节点的地址值
        Entry right;      // 右子节点的地址值
        Entry parent;     // 父节点的地址值
}
List集合
List介绍和常用方法知识点:
List集合体系有什么特点
List接口中特有的按照索引操作的方法有哪些
![](./img/单列集合体系.bmp)总结:
List集合体系的特点:
        1. 元素存取有序 (存入和取出元素的顺序一致) 321->321  排序: 从小到大
        2. 元素可以重复  1 1 1 1
        3. 有索引
List子体系中的实现类都具有上述特点java.util.List接口:
        // 常用特有成员方法 (都是按照索引来操作的)   
        void add(int index, E element): 将指定的元素, 添加到该集合中的指定位置上
        E get(int index): 返回集合中指定位置的元素
        E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素
        E set(int index, E element): 用指定元素替换集合中指定位置的元素, 返回值的更新前的元素
补充: ArrayList集合的特点知识点:
ArrayList底层使用的是什么数据结构, 有什么特点
ArrayList适用于什么场景
总结:
ArrayList底层的数据结构:
        数组
       
ArrayList的特点:
        查询快
        增删慢
        线程不安全, 效率高
       
ArrayList适用场景:
        存储的数据"查询多, 增删少"的场景. 如用一个ArrayList存储中国城市名称
补充: LinkedList集合的特点和特有方法知识点:
LinkedList底层使用的是什么数据结构, 有什么特点
LinkedList适用于什么场景
LinkedList有哪些特有方法
总结:
LinkedList底层的数据结构:
        链表
       
LinkedList的特点:
        查询慢
        增删快
        线程不安全, 效率高
       
LinkedList适用场景:
        存储的数据"查询少, 增删多"的场景. 如用LinkedList实现栈或队列
       
java.util.LinkedList<E>类: 链表结构, 查询慢, 增删快
        // 特有成员方法(主要操作开头和末尾元素)
        void addFirst(E e): 将指定元素插入此列表的开头
        void addLast(E e): 将指定元素添加到此列表的结尾
        E getFirst(): 返回此列表的第一个元素
        E getLast(): 返回此列表的最后一个元素
        E removeFirst(): 移除并返回此列表的第一个元素
        E removeLast(): 移除并返回此列表的最后一个元素
        E pop(): (其实就是removeFirst())从此列表所表示的栈中弹出一个元素
        void push(E e): (其实就是addFirst())将元素添加到此列表所表示的栈中
补充: 5分钟练习: 测试LinkedList特有方法
需求:
创建LinkedList集合, 添加元素1,2,3, 测试特有方法:
        void addFirst(E e): 将指定元素插入此列表的开头
        void addLast(E e): 将指定元素添加到此列表的结尾
        E getFirst(): 返回此列表的第一个元素
        E getLast(): 返回此列表的最后一个元素
        E removeFirst(): 移除并返回此列表的第一个元素
        E removeLast(): 移除并返回此列表的最后一个元素
        E pop(): (其实就是removeFirst())从此列表所表示的栈中弹出一个元素
        void push(E e): (其实就是addFirst())将元素添加到此列表所表示的栈中
代码:
public class Test {
    public static void main(String[] args) {
        // 创建LinkedList集合
        LinkedList<Integer> linked = new LinkedList<>();        // 添加元素1,2,3
        //void addFirst(E e): 将指定元素插入此列表的开头
        linked.addFirst(1);
        linked.addFirst(2);
        linked.addFirst(3);
        System.out.println(linked);  // 都是添加到头部, 所以是 3 2 1        // void addLast(E e): 将指定元素添加到此列表的结尾
        linked.addLast(7);
        linked.addLast(8);
        linked.addLast(9);
        System.out.println(linked);  // 都是添加到末尾, 所以是 3 2 1 7 8 9        // E getFirst(): 返回此列表的第一个元素
        System.out.println(linked.getFirst());  // 3        // E getLast(): 返回此列表的最后一个元素
        System.out.println(linked.getLast());  // 9        // E removeFirst(): 移除并返回此列表的第一个元素
        Integer i1 = linked.removeFirst();
        System.out.println("删除开头:" + i1);  // 3        // E removeLast(): 移除并返回此列表的最后一个元素
        Integer i2 = linked.removeLast();
        System.out.println("删除末尾:" + i2);  // 9        // E pop(): (其实就是removeFirst())从此列表所表示的栈中弹出一个元素
        Integer pop = linked.pop();
        System.out.println("pop()取出的是:" + pop);  // 2        // void push(E e): (其实就是addFirst())将元素添加到此列表所表示的栈中
        linked.push(666);
        System.out.println(linked);  // [666, 1, 7, 8]
    }
}
Vector集合知识点:
Vector底层使用的是什么数据结构, 有什么特点
总结:
JDK 1.0 版本中只有一个 Vector集合
JDK 1.2 开始增加了Collection集合体系Vector底层的数据结构:
        数组
       
Vector的特点:
        查询慢
        增删快
        (同步)线程安全, 效率低
       
Vector目前几乎没人使用
补充: Set集合体系
HashSet集合知识点:
Set集合体系有什么特点
HashSet有什么特点, 底层采用什么数据结构
HashSet中的 boolean add(E e) 方法有什么特殊之处
![](./img/单列集合体系.bmp)总结:
Set集合体系特点:
        1. 元素不可重复
        2. 没有索引
       
HashSet特点:
        1. 元素不可重复
        2. 没有索引
        3. 元素存取无序 (存入和取出顺序有可能不一致)
        4. 底层采用 哈希表 结构. (查询快)
                哈希表 = 数组 + 链表或红黑树java.util.HashSet类:
        // 常用方法
        boolean add(E e): 添加元素, 根据元素的 hashCode() 和 equals() 方法判断是否重复. 重复则不添加并返回false, 不重复则添加并返回true
补充: 5分钟练习: 使用HashSet添加元素
需求:
创建HashSet对象, 存储 5,5,4,4,3,3,2,2,1,1, 使用增强for遍历HashSet集合打印元素, 查看是否和存入顺序一致, 是否有重复元素
代码:
public class Test {
    public static void main(String[] args) {
        // 创建HashSet对象
        HashSet<Integer> hashSet = new HashSet<>();        // 添加元素
        hashSet.add(5);
        hashSet.add(5);
        hashSet.add(4);
        hashSet.add(4);
        hashSet.add(3);
        hashSet.add(3);
        hashSet.add(2);
        hashSet.add(2);
        hashSet.add(1);
        hashSet.add(1);        // 使用增强for遍历HashSet集合打印元素
        for (Integer i : hashSet) {
            System.out.println(i);
        }        /*
            1
            2
            3
            4
            5
         */
    }
}
HashSet原理: 哈希值知识点:
什么是哈希值, 哈希值有什么作用
Object类中的 int hashCode() 方法有什么作用
总结:
哈希值:
        一个十进制数值, 一般是通过将该对象的内部地址转换成一个整数来实现的public native int hashCode();
        可以调用系统本地代码(C/C++)计算出一个对象地址的哈希值
       
hashCode()方法的作用
        方法内部的算法用于将对象计算为一个哈希值, 便于根据哈希值比较对象是否"相等"
        哈希值主要是为了提高对象存储在 哈希表 中的效率
       
注意:
        1. 如果我们不满意Object中的哈希值计算方法, 可以重写hashCode()方法.
       但在Java代码中不能直接重写带有 native 的方法, 重写时应该将 native 去掉
                        @Override
                        public int hashCode() {}
        2. hashCode() 方法有可能将"不同的对象"计算出"相同的哈希值", 这称为"哈希冲突", 在出现冲突后, 一般再通过 equals() 方法来继续判断对象是否"相等"
        
        "重地"  "通话"
补充: HashSet原理: 哈希表结构知识点:
JDK 8以前, 哈希表是什么结构
JDK 8及之后, 哈希表是什么结构
总结:
哈希表:
        JDK 8以前   : 哈希表 = 数组 + 链表
        JDK 8及之后 : 哈希表 = 数组 + 链表或红黑树
        数组中存储的每个元素, 是哈希值相同的一组节点的链表或红黑树![](./img/05_HashSet集合存储数据的结构(哈希表).bmp)补充: HashSet原理: 存储元素不重复的原理知识点:
HashSet集合是如何保证添加元素时不能重复的
总结:
HashSet集合保证添加元素不重复的原理:
        调用 add(E e) 添加元素时, 先调用 hashCode() 获取哈希值, 和当前HashSet集合中的元素比较
                如果哈希值不同, 则认为元素不重复, 添加, 并返回true
                如果哈希值相同, 则可能是哈希冲突, 所以继续调用元素的 equals() 方法和所有哈希值相同的元素比较
                        如果 equals() 比较所有元素都没有相同的, 则认为元素不重复, 添加, 并返回true
                        如果 equals() 比较出有相同的元素, 则认为元素重复, 不添加, 并返回false![](./img/06_Set集合存储元素不重复的原理.bmp)补充: HashSet存储自定义元素的去重知识点:
我们自定义的JavaBean对象存入HashSet时, 想"根据属性值保证不重复", 应该怎么做
总结:
自定义JavaBean对象实现在HashSet中去重:
        JavaBean默认继承Object类中的 hashCode() 和 equals() 方法, 都是根据对象地址值判断是否重复的
        要根据属性值判断是否重复, 应该在JavaBean类中重写 hashCode() 和 equals() 方法, 使其按照属性值比较
补充: 5分钟练习: 自定义Person类存入HashSet实现去重
需求:
定义Person类:
        私有成员变量: 姓名String name, 年龄int age
        生成无参/有参构造, set/get方法, toString()方法
        生成 hashCode() 和 equals() 方法
定义测试类
        创建3个Person对象, 其中2个对象的姓名和年龄均相同, 另外1个对象姓名或年龄不同
        创建HashSet集合, 存入3个Person对象, 打印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 +
                '}';
    }    // 若要实现去重, 要生成: Alt + Insert 选择 equals() and hashCode()    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}public class Test {
    public static void main(String[] args) {
        // 创建3个Person对象
        Person p1 = new Person("张三", 13);
        Person p2 = new Person("张三", 13);
        Person p3 = new Person("李四", 13);        // 创建HashSet集合
        HashSet<Person> set = new HashSet<>();        set.add(p1);
        set.add(p2);
        set.add(p3);        // 打印
        System.out.println(set);
        // [Person{name='张三', age=13}, Person{name='李四', age=13}]
    }
}
LinkedHashSet集合知识点:
LinkedHashSet有什么特点
LinkedHashSet底层是什么数据结构
总结:
LinkedHashSet特点:
        1. 元素存取有序 (存入和取出顺序一致)
        2. 元素不可重复
        3. 没有索引
       
LinkedHashSet底层数据结构:
        哈希表 + 链表   (也就是: 数组 + 链表或红黑树 + 链表)
        其中, 哈希表用于存储数据, 额外的链表用于记录元素添加时的先后顺序, 以便在获取元素时保持顺序一致
补充:
总结: 什么时候用List, 什么时候用Set?
        要存储的元素可以重复的, 用List集合:
                增删少, 用ArrayList
                增删多, 用LinkedList
        要存储的数据要求不重复, 或者相对一个集合去重, 用Set集合:
                不要求存取顺序一致, 用HashSet
                要求存取顺序一致, 用LinkedHashSet
5分钟练习: 使用LinkedHashSet存储元素
需求:
创建LinkedHashSet对象, 存储 5,5,4,4,3,3,2,2,1,1, 使用增强for遍历LinkedHashSet集合打印元素, 查看是否和存入顺序一致
代码:
public class Test {
    public static void main(String[] args) {
        // 创建LinkedHashSet对象
        LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>();        // 添加元素
        linkedHashSet.add(5);
        linkedHashSet.add(5);
        linkedHashSet.add(4);
        linkedHashSet.add(4);
        linkedHashSet.add(3);
        linkedHashSet.add(3);
        linkedHashSet.add(2);
        linkedHashSet.add(2);
        linkedHashSet.add(1);
        linkedHashSet.add(1);        // 遍历
        for (Integer i : linkedHashSet) {
            System.out.println(i);
        }
        // 去重了, 并同时保证了存取顺序一致
        /*
            5
            4
            3
            2
            1
         */
    }
}
可变参数知识点:
什么是可变参数
可变参数用在哪里, 格式是什么
可变参数的本质是什么
可变参数可以传递的参数个数有什么要求
可变参数的定义位置有什么要求
总结:
可变参数:
        JDK 5 出现. 指同一个类型的参数, "个数可变"
        可变参数的本质就是一个"数组"
       
        格式: 用在方法的参数中
            修饰符 返回值类型 方法名(int... 变量名) {
                    // 可以直接将 变量名 当作 数组名 使用
            }
            方法名();注意事项:
        1. 可变参数可以传递的参数个数, 可以是 0个, 1个, 多个
        2. 一个方法的参数列表中, 只能有一个可变参数
        3. 如果方法的参数有多个, 可变参数必须写在参数列表的最后
补充: Collections集合工具类
Collections集合工具类: addAll(), shuffle()知识点:
Collections集合工具类的常用方法有哪些
总结:
java.util.Collections类: 操作集合的工具类
        // 静态方法
        static <T> boolean addAll(Collection<? super T> c, T... elements):往集合中添加一些元素
        static void shuffle(List<?> list): 打乱集合顺序
        static <T> void sort(List<T> list): 将集合中元素按照默认规则排序
        static <T> void sort(List<T> list,Comparator<? super T> c):将集合中元素按照指定规则排序
补充: 5分钟练习: 测试addAll()和shuffle()方法
需求:
创建ArrayList集合, 使用 Collections.addAll() 方法, 向集合中添加1,2,3,4,5
然后调用shuffle()方法打乱该集合的顺序, 打印集合查看效果
代码:
public class Test {
    public static void main(String[] args) {
        // 创建集合
        ArrayList<Integer> list = new ArrayList<>();        // 添加多个元素
        Collections.addAll(list, 1, 2, 3, 4, 5);        // 打乱
        Collections.shuffle(list);        // 打印
        System.out.println(list);
    }
} Collections集合工具类: sort(List<T> list)知识点:
void sort(List<T> list) 方法按照什么规则将元素排序
是不是所有类型的元素都能排序
该方法有什么使用前提
自定义JavaBean对象要想排序, 需要怎么做
总结:
sort(List<T> list): 默认按照"升序"将元素排序
        数字, 字母, 都可以按照升序排序
       
自定义JavaBean对象默认不能排序, 因为不知道如何比较哪个对象大, 哪个对象小
自定义JavaBean对象要想排序, 需要实现 Comparable<E> 接口, 重写 int compareTo(E e) 方法
        规则:
                this-参数: 升序(从小到大)
                参数-this: 降序(从大到小)
补充: 5分钟练习: 实现Person排序
需求:
定义Person类, 实现Comparable接口, 泛型为Person:
        私有成员变量: 姓名String name, 年龄int age
        生成无参/有参构造, set/get方法, toString()
        重写int compareTo(E e)方法
                方法内部根据Person对象的年龄计算大小
定义测试类
        创建3个Person对象, 分别为:
                李四, 14
                张三, 13
                王五, 15
        创建ArrayList集合, 存储3个Person对象
        调用 Collections.sort() 方法, 对集合排序, 然后使用增强for遍历输出结果, 查看是否排序
代码:
public class Person implements Comparable<Person>{  // 注意写上泛型    @Override
    public int compareTo(Person o) {
        return this.getAge() - o.getAge();  // 按照年龄升序排序
    }    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 +
                '}';
    }
}public class Test {
    public static void main(String[] args) {
        // 创建3个Person对象
        Person p1 = new Person("李四", 14);
        Person p2 = new Person("张三", 13);
        Person p3 = new Person("王五", 15);        // 创建集合
        ArrayList<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        System.out.println("排序前:" + list);        // 排序
        Collections.sort(list);
        System.out.println("排序后:" + list);
        /*
排序前:[Person{name='李四', age=14}, Person{name='张三', age=13}, Person{name='王五', age=15}]
排序后:[Person{name='张三', age=13}, Person{name='李四', age=14}, Person{name='王五', age=15}]
         */
    }
}
Collections集合工具类: sort(List<T> list,Comparator<? super T> )知识点:
void sort(List<T> list,Comparator<? super T> c) 方法的第二个参数是什么, 如何使用
Comparable接口和Comparator接口有什么区别
自定义JavaBean对象要想利用该方法排序, 需要怎么做
总结:
Comparable接口和Comparator接口区别
        Comparable: 让JavaBean自身具有可比较性 (自己和其他人比)
        Comparator: 定义一个比较器类, 用比较器对象比 (让第三个人来帮两个人比较)Comparator使用方式:
        1. 定义类实现Comparator<E>接口, 重写 int compare(E o1, E o2) 方法, 泛型为比较元素的类型
                规则:
            o1-o2: 升序(从小到大)
            o2-o1: 降序(从大到小)
        2. 在Collections.sort(List<T> list,Comparator<? super T> c)方法中传入自定义比较器对象
补充: 5分钟练习: 使用Comparator对Person集合排序
需求:
定义Person类:
        私有成员变量: 姓名String name, 年龄int age
        生成无参/有参构造, set/get方法, toString()
定义测试类
        创建3个Person对象, 分别为:
                李四, 14
                张三, 13
                王五, 15
        创建ArrayList集合, 存储3个Person对象
        调用Collections.sort(List<T> list,Comparator<? super T> c)方法, 对集合排序, 比较器使用匿名内部类对象方式, 按照Person对象的年龄排序
        然后使用增强for遍历输出结果, 查看是否排序
代码:
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 +
                '}';
    }
}public class Test {
    public static void main(String[] args) {
        // 创建Person对象
        Person p1 = new Person("李四", 14);
        Person p2 = new Person("张三", 13);
        Person p3 = new Person("王五", 15);        // 创建ArrayList
        ArrayList<Person> list = new ArrayList<>();        list.add(p1);
        list.add(p2);
        list.add(p3);
        System.out.println("排序前:" + list);        // 排序
        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge(); // 按照年龄升序
            }
        });        System.out.println("排序后:" + list);
    }
}
今日API
java.util.List<E>接口:
        // 常用特有成员方法 (都是按照索引来操作的)
        public void add(int index, E element): 将指定的元素, 添加到该集合中的指定位置上
        public E get(int index): 返回集合中指定位置的元素
        public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素
        public E set(int index, E element): 用指定元素替换集合中指定位置的元素, 返回值的更新前的元素java.util.LinkedList<E>类: 链表结构, 查询慢, 增删快
        // 特有成员方法(主要操作开头和末尾元素)
        void addFirst(E e): 将指定元素插入此列表的开头
        void addLast(E e): 将指定元素添加到此列表的结尾
        E getFirst(): 返回此列表的第一个元素
        E getLast(): 返回此列表的最后一个元素
        E removeFirst(): 移除并返回此列表的第一个元素
        E removeLast(): 移除并返回此列表的最后一个元素
        E pop(): (其实就是removeFirst())从此列表所表示的堆栈处弹出一个元素 栈stack
        void push(E e): (其实就是addFirst())将元素推入此列表所表示的堆栈
       
java.util.Set<E>接口:
        // 成员方法
        boolean add(E e): 添加元素. 元素不重复则添加成功, 返回true; 否则返回false
       
java.util.Collections类: 操作集合的工具类
        // 静态方法
        static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素
        static void shuffle(List<?> list) :打乱集合顺序
        static <T> void sort(List<T> list) :将集合中元素按照默认规则排序
        static <T> void sort(List<T> list,Comparator<? super T> c):将集合中元素按照指定规则排序
**单列集合体系:**
Collection接口: 单列集合的根接口, 规定了公共的功能
        |
        |_ List接口: 元素存取有序, 可重复, 有索引
        |        |_ Vector类: 底层数组, 有索引, 内存空间连续分配, 查询快, 增删慢, 线程安全, 效率低
        |        |_ ArrayList类: 底层数组, 有索引, 内存空间连续分配, 查询快, 增删慢, 线程不安全, 效率高
        |        |_ LinkedList类: 底层链表, 查询慢, 增删快
        |        |_ 遍历
        |                - toArray(): 可以
        |                - 普通for: 可以
        |                - 增强for: 可以
        |                - 迭代器: 可以
        |
        |_ Set接口: 元素不可重复, 无索引
                |_ HashSet类: 底层哈希表, 元素无序, 元素不可重复(用hashCode()和equals()方法来判断)
                |        |_ LinkedHashSet类: 哈希表+链表, 同时具有HashSet的元素不重复, 链表存取有序的特点
                |
                |_ TreeSet类: 底层红黑树结构(存入元素时就会按照元素自然顺序排序).
                |       
                |_ 遍历
                        - toArray(): 可以
                        - 普通for: 不可以, 没有索引, 不能用!
                        - 增强for: 可以
                        - 迭代器: 可以
今日目标 能够说出List集合特点
        1. 元素存取有序
        2. 可以存储重复元素
        3. 有索引
能够说出常见的数据结构
        栈
        队列
        数组
        链表
        红黑树
        哈希表
能够说出数组结构特点
        查询快, 增删慢
能够说出栈结构特点
        先进后出
        出口和入口在同一侧
能够说出队列结构特点
        先进先出
        出口和入口在两侧
能够说出单向链表结构特点
        由节点组成
        遍历: 从开头一直到末尾查询慢, 增删快
能够说出Set集合的特点
        1. 元素不能重复
        2. 没有索引
能够说出哈希表的特点
        哈希表 = 数组 + 链表/红黑树去重:
        add() 先使用hashCode()方法计算哈希值, 判断哈希值是否有重复
                如果没有重复的, 说明没有重复, 直接添加
                如果有重复的哈希值, 是哈希冲突, 继续使用元素的equals()方法来判断是否重复
                        如果 equals()判断全都不一样, 说明不重复, 可以添加
                        如果 equals()判断有重复的, 说明重复, 不能添加
使用HashSet集合存储自定义元素
        HashSet: 去重自定义元素要重写 hashCode() equals()方法
能够说出可变参数的格式
        方法名(数据类型... 变量名) {
                        // 当作数组来使用
        }注意事项:
                参数列表中只能有1个可变参数
                放在列表的最后
                传递参数的个数0~n个
能够使用集合工具类
        Collections类
                static boolean addAll(Collection c, T... t)
                static void shuffle(List list)
                static void sort(List list): 元素实现Comparable接口
                static void sort(List list, Comparator c)
能够使用Comparator比较器进行排序
        1. 定义实现类实现Comparator接口, 重写 int compare(E o1, E o2)
                规则:
                        o1-o2 升序
                        o2-o1 降序
2. 创建实现类对象, 传递到 static void sort(List list, Comparator c) 方法中




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2