2021-09-03

集合

Collection

1. Collection概述

  • Collection是单列集合的顶层窗口,他表示一组对象,这些对象也称为Collection的元素。

  • JDK不提供此接口的任何直接实现,他提供更具体的子接口(如Set和List)实现。

2. 创建集合对象

  1. 多态的方式

  1. 具体实现类ArrayList

3. Collection 集合常用方法

  1. bollean add(E e)添加元素

  2. bollean remove(Object o) 从集合中移除指定的元素

  3. bollean contains(Object o) 判断集合中是否存在某种元素

  4. void clear() 清空集合中的元素

  5. bollean is Empty 判断集合是否为空

  6. int size() 集合的长度/集合中的元素个数

4. 集合的遍历

  • Interator迭代器(集合的专用遍历方式)

  • Interator<E> iterator() 返回次集合中的元素迭代器

  1. 通过集合的iterator方法得到

  2. 迭代器是通过集合的iterator()方法得到,他是依赖于集合而存在

5. Iterator常用方法

  1. E next() 返回迭代器的下一个元素

  2. bollean hasNext() 如果迭代器具有更多元素则返回true

List集合

  • 有序集合,用户可以精确控制列表中的每一个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素

  • 与Set集合不同,列表通常允许重复元素

1. 并发修改异常

产生原因

  • 迭代器遍历的过程中,通过集合对象修改了集合中的元素长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致

  • 使用for循环遍历可以避免该异常

2. ListLterator列表迭代器

  1. 通过List集合的listIterator()方法得到,他是List集合特有的迭代器

  2. 允许沿任一方向遍历列表,并获取列表中迭代器当前位置

3. ListIterator中的常用方法

  1. E next() 返回迭代器中的下一个元素

  2. bollean hasNext() 如果迭代器具有更多元素则返回true

  3. E previous() 返回列表中的上一个元素

  4. bollean hasPrevious() 如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回True

  5. void add(E e) 将指定元素插入列表(此方法不会抛出并发修改异常)

4.增强for循环

  • 增强for:简化数组和Collection集合的遍历

    1. 实现Iterator接口的类允许其对象成为增强型for语句的目标

    2. 它是JDK5以后出现,其内部是一个Iterator迭代器

  • 增强for格式

    for(元素数据类型 变量名:数组或者Collection集合){
        //在此处使用变量即可,该变量就是元素。
    }

5.数据结构

  1. 数据先进后出

  2. 队列

    先进先出

  3. 数组

    数组是一个查询快,增删慢的模型

  4. 链表

    链表每个元素称为结点

    链表增删慢,查询快(对比数组)

6.List集合子类特点

  • List集合常用子类 ArrayList,LinkedList

  • ArrayList 底层数据结构是数组

  • LinkedList 底层数据结构是链表

7.LinkedList特有功能

add First 添加元素到第一位置
add Last 添加元素最后位置
get First 返回此列表中第一个元素
get Last 返回此列表中最后一个元素
remove First 从此列表中删除并返回第一个元素
remove Last 从此列表中删除并返回最后一个元素

Set集合

  • 不包含重复元素的集合

  • 没有索引的方法,不能使用普通for循环遍历

1.Hash Set

  • 对集合的迭代顺序不作任何保证

2.哈希值

  • 是根据对象的地址或字符串或数字算出来得int类型的数值

  • Object类中有一个方法可以获取对象的哈希值

    public int hashCode() 返回对象的哈希值
    1. 同一个对象多次调用hashCode()方法返回的哈希值相同

    1. 不同对象的哈希值是不相同的(默认情况),通过方法重写可以实现不同对象的哈希值相同

    1. 字符串重写了hashCode()方法

3.HashSet集合

  1. 底层数据结构是哈希表

  2. 对集合的迭代顺序不保证,不保证存储和取出元素顺序一致

  3. 没有带索引的方法,不能使用普通for循环遍历

  4. 由于是Set集合,不包含重复的元素集合

4.哈希表

  • JDK8前采用数据+链表实现可以说是一个元素为链表的数组

  • JDK8以后在长度较长时底层实现了优化

5.LinkedHashSet特点

  1. 哈希表和链表实现的Set接口,具有可预测的迭代次序

  2. 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的

  3. 由哈希表保证元素唯一,没有重复元素

6.TreeSet<E>集合

  1. 元素有序:不是存储和取出顺序,而是按照一定顺序进行排序,具体排序方式取决于构造方法

  2. TreeSet() 根据元素的自然排序进行排序
    TreeSetComparator(comparator) 根据指定的比较器进行排序
  3. 没有带索引的方法

  4. 由于是Set集合,没有重复元素

  5. 集合中不能存储基本元素类型只能使用对应的包装类类型

  6. 集合只能存储引用类型

7.自然排序Comparable的使用

class Student{
    @Override
    public int compareTo(Student s){
        int num = this.age - s.age;
        //年龄相同时,按照姓名的字母排序
        int num2 = num == 0?this.name.compareTo(s.name):num;
        return num2;
    }
}

public class TressSetDemo02{
    //Student类应该实现Comparable接口并重写compareTo()方法
    public static void main(String[] args){
        //创建集合对象
        TreeSet<Stdudent> ts = new TreeSet<Student>();
        //创建学生对象
        Student S1 = new Student("xishi",29);
        Student S2 = new Student("xishi1",30);
        Student S3 = new Student("xishi2",31);
        Student S4 = new Student("xishi3",32);
        //把学生添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        //遍历集合
        for(Student s : ts){
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
}

结论

  1. 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序

  2. 自然排序,就是让元素所属类实现Comparable接口,重写comparableTo(To)方法

  3. 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

8.比较器排序Comparator的使用

  • 存储学生对象并遍历,创建TreSet集合使用带参构造方法

  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

public class TreeSetDemo{
    //创建集合对象
    TreeSet<Student> ts = new TreeSet<Student>(new comparator<Student>(){
        @Override
        public int compare(student s1,Student s2){
            int num = s1.getAge() - s2.getAge();
            int num2 = num == 0? s1.getName().compareTo(s2.getName());
            return num2;
            
        }
    });
     //创建学生对象
        Student S1 = new Student("xishi",29);
        Student S2 = new Student("xishi1",30);
        Student S3 = new Student("xishi2",31);
        Student S4 = new Student("xishi3",32);
        //把学生添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
     //遍历集合
        for(Student s : ts){
            System.out.println(s.getName() + "," + s.getAge());
        }
}

结论

  • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器对元素进行排序的

  • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(To1,To2)方法

  • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

泛型

1.泛型概述

  • 是JDK5中引入的特性,他提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型,它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数

  • 一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?

    顾名思义,就是将类型由原来的具体类型参数化,然后在使用/调用时传入具体的类型

    这种参数类型可以用在类,方法和接口中,分别被称为泛型类,泛型方法,泛型接口

2.泛型定义格式

  • <类型> :指定一种类型的格式。这里的类型可以看成是形参

  • <类型1,类型2...>:指多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参

  • 将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型

3.泛型的好处

  • 把运行时期的问题提前到了编译期间

  • 避免了强制类型转换

4.泛型类

泛型类的定义格式:

  • 格式:修饰符class 类名<类型>{}

  • 范例:public class Generic<T>{}

    此处T可以随意写为任意标识,常见的如T,E,K,V等形式的参数常用于表示泛型

5.泛型方法

泛型方法的定义格式:

  • 格式:修饰符<类型> 返回值类型 方法名(类型 变量名){}

  • 范例:public<T> void show(T t){}

6.泛型接口

泛型接口的定义格式

  • 格式:修饰符 interface 接口名<类型>{}

  • 范例:public interface Generic<T>{}

7.类型通配符

为了表示各种泛型List的父类,可以使用类型通配符

  • 类型通配符:<?>

  • List<?>:表示元素类型未知的List,它的元素可以匹配任何类型

  • 这种带通配符的List仅表示他是各种泛型的List父类,并不能把元素添加到其中

    List<?> list1 = new ArrayList<Object>();

    如果说我们不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限

    • 类型通配符上限:<?extends 类型>

    • List<?extends Numbre>:他表示的类型是Number或者其子类型

      List<?extends Number> list5 = new ArrayList<Number>();

    除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限

    • 类型通配符下限:<? super 类型>

    • List<? super Number>:他表示的类型是Number或者其父类型

      List<? super Number> list5 = new ArrayList<Object>();

8.可变参数

可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了

  • 格式:修饰符 返回值类型 方法名(数据类型...变量名){}

  • 范例:public static int sum(int...a){}

可变参数注意事项

  • 这里的变量其实是一个数组

  • 如果一个方法有多个参数,包含可变参数,可变参数要放到最后

9.可变参数的使用

Arrays工具类中有一个静态方法:

  • public static <T> List<T>aslist(T...a):返回由指定数组支持的固定大小的列表

  • 返回的集合不能做增删操作,可以做修改操作

List接口中有一个静态方法:

  • public static <E>List<E>of(E...elements):返回包含任意数量元素的不可变列表

  • 返回的集合不能做增删改操作

Set接口中有一个静态方法:

  • public static<E>Set<E>of(E...elements):返回一个包含任意数量元素的不可变集合

  • 返回的集合不能做增删操作,没有修改的方法,不能传相同的参数

案例

1.成绩排序

需求

  • 用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合

  • 要求:按照总分从高到低出现

思路

  • 定义学生类

  • 创建TreeSet类对象,通过比较器排序进行排序

  • 创建学生对象

  • 把学生对象添加到集合

  • 遍历集合

    package com.Wss02;
    ​
    public class Student {
        private String name;
        private int chinese;
        private int math;
    ​
        public Student(String name, int chinese, int math) {
            this.name = name;
            this.chinese = chinese;
            this.math = math;
        }
    ​
        public Student() {
        }
    ​
        public String getName() {
            return name;
        }
    ​
        public void setName(String name) {
            this.name = name;
        }
    ​
        public int getChinese() {
            return chinese;
        }
    ​
        public void setChinese(int chinese) {
            this.chinese = chinese;
        }
    ​
        public int getMath() {
            return math;
        }
    ​
        public void setMath(int math) {
            this.math = math;
        }
    ​
        public int getSum() {
            return this.chinese + this.math;
        }
    ​
    }​
    
package com.Wss02;
​
import java.util.Comparator;
import java.util.TreeSet;
​
public class TreeSetDemo {
    public static void main(String[] args) {
        //创建TreeSet类对象,通过比较器排序进行排序
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
//             int num = (s2.getChinese()+s2.getMath())-(s1.getMath()+s2.getChinese());
                int num = s1.getSum() - s2.getSum();
                int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
                int num3 = num2 == 0 ? s1.getName().compareTo(s2.getName()) : num2;
                return num3;
            }
        });
        Student s1 = new Student("金旭1", 100, 200);
        Student s2 = new Student("金旭2", 101, 210);
        Student s3 = new Student("金旭3", 100, 230);
        Student s4 = new Student("金旭4", 100, 200);
        Student s5 = new Student("金旭5", 100, 200);
//        把学生对象添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        //遍历集合
        for (Student s : ts) {
            System.out.println(s.getName() + "," + s.getChinese() + "," + s.getMath() + "," + s.getSum());
        }
    }
}
​

2.不重复的随机数

需求

  • 编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并在控制台输出

思路

  • 创建Set集合对象

  • 创建随机数对象

  • 判断集合长度是不是小于10

    • 是:产生一个随机数,添加到集合

    • 回到判断

  • 遍历集合

package com.Wss03;
​
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
​
public class SetDemo {
    public static void main(String[] args) {
//        创建Set集合对象
//        Set<Integer> set = new HashSet<Integer>();
        Set<Integer> set = new TreeSet<Integer>();
//        创建随机数对象
        Random r = new Random();
//        判断集合长度是不是小于10
        while (set.size()<10){
            int number = r.nextInt(20) + 1;
            set.add(number);
        }
        for (Integer i : set){
            System.out.println(i);
        }
    }
}
​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用python中的pymsql完成如下:表结构与数据创建 1. 建立 `users` 表和 `orders` 表。 `users` 表有用户ID、用户名、年龄字段,(id,name,age) `orders` 表有订单ID、订单日期、订单金额,用户id字段。(id,order_date,amount,user_id) 2 两表的id作为主键,`orders` 表用户id为users的外键 3 插入数据 `users` (1, '张三', 18), (2, '李四', 20), (3, '王五', 22), (4, '赵六', 25), (5, '钱七', 28); `orders` (1, '2021-09-01', 500, 1), (2, '2021-09-02', 1000, 2), (3, '2021-09-03', 600, 3), (4, '2021-09-04', 800, 4), (5, '2021-09-05', 1500, 5), (6, '2021-09-06', 1200, 3), (7, '2021-09-07', 2000, 1), (8, '2021-09-08', 300, 2), (9, '2021-09-09', 700, 5), (10, '2021-09-10', 900, 4); 查询语句 1. 查询订单总金额 2. 查询所有用户的平均年龄,并将结果四舍五入保留两位小数。 3. 查询订单总数最多的用户的姓名和订单总数。 4. 查询所有不重复的年龄。 5. 查询订单日期在2021年9月1日至9月4日之间的订单总金额。 6. 查询年龄不大于25岁的用户的订单数量,并按照降序排序。 7. 查询订单总金额排名前3的用户的姓名和订单总金额。 8. 查询订单总金额最大的用户的姓名和订单总金额。 9. 查询订单总金额最小的用户的姓名和订单总金额。 10. 查询所有名字中含有“李”的用户,按照名字升序排序。 11. 查询所有年龄大于20岁的用户,按照年龄降序排序,并只显示前5条记录。 12. 查询每个用户的订单数量和订单总金额,并按照总金额降序排序。
06-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值