0
点赞
收藏
分享

微信扫一扫

Java系列(40)——集合(下)

闲嫌咸贤 2022-03-30 阅读 172


本系列博客汇总在这里:Java系列_汇总


目录

  • ​​一、Set 集合(接口)​​
  • ​​二、Set 集合的实现类 HashSet​​
  • ​​1、HashSet 集合的特点​​
  • ​​2、HashSet 是如何判断元素重复的​​
  • ​​三、Set 集合的实现类 LinkedHashSet​​
  • ​​LinkedHashSet 特点​​
  • ​​四、Set 集合的实现类 TreeSet​​
  • ​​1、TreeSet 特点​​
  • ​​2、自定义排序​​
  • ​​五、可变参数​​
  • ​​六、Arrays 工具类​​
  • ​​七、集合工具类​​

一、Set 集合(接口)

Java系列(40)——集合(下)_ide

二、Set 集合的实现类 HashSet

  1. HashSet 实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持,它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变,此类允许使用 null 元素。
  2. List 允许重复以及存在空值(可以多个)的。

1、HashSet 集合的特点

  1. 无序性 (跟添加的顺序无关);
  2. 不能重复 ;
  3. 允许有 null,但是只能有一个;
  4. HashSet 不是线程安全的。

2、HashSet 是如何判断元素重复的

  1. Set 在添加元素的时候会拿这个元素和集合中的每一个元素做比较,如果重复了就不添加,如果没有重复就添加。
  2. 在判断字符串是否重复的时候,是调用了 String 类里面的 equals() 方法;另外,判断两个对象是否相等,必须要重写 equals 和 hashCode 方法,这两个方法都符合相等的条件才认为是相等的两个对象,如下:
    Java系列(40)——集合(下)_ide_02
  3. 重写 equals 和 hashCode 方法
  4. package cn.tx.set;
    public class Person
    {
    private int id;
    private String name;
    private int age;
    // 构造器
    public Person(int id, String name, int age)
    {
    super();
    this.id = id;
    this.name = name;
    this.age = age;
    }
    public int getId()
    {
    return id;
    }
    public void setId(int id)
    {
    this.id = id;
    }
    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;
    }
    // 重写tostring方法
    @Override
    public String toString()
    {
    return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
    }
    /**
    * 重写equal方法
    */
    @Override
    public boolean equals(Object obj)
    {
    // 判断是否是person类的实例
    if (!(obj instanceof Person))
    {
    return false;
    }
    // 把传递过来的对象转换成子类
    Person person = (Person) obj;
    // 如果两个person的所有属性都相等我们认为是相同的person
    if (this.id == person.id && this.name != null && person.name != null && this.name.equals(person.name) && this.age == person.age)
    {
    return true;
    } else
    {
    return false;
    }
    }
    /**
    * 重写hashCode
    */
    @Override
    public int hashCode()
    {
    //返回同一个值
    return 1;
    }
    }
    // 创建一个set的集合
    Set<Person> set = new HashSet<Person>();
    set.add(new Person(1, "诸葛亮", 26));
    set.add(new Person(2, "刘成娟", 36));
    set.add(new Person(1, "诸葛亮", 26));
    System.out.println(set);
  5. Java系列(40)——集合(下)_字符串_03

三、Set 集合的实现类 LinkedHashSet

  1. LinkedHashSet 具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。
  2. LinkedHashSet 的方法几乎都是继承于 HashSet,不同在于 LinkedHashSet 是有序的。

LinkedHashSet 特点

  1. 有序性(添加顺序);
  2. 不能重复;
  3. 允许有null,但是只能有一个;
  4. 不是同步的(不是线程安全的,效率高)。

四、Set 集合的实现类 TreeSet

  TreeSet 可以支持自定义排序,如果 TreeSet 所存储的对象的类没有实现 Comparable 接口就会抛出异常 ClassCastException,所以我们如果想要使用TreeSet来对自定义的对象来排序必须实现Comparable 接口。

1、TreeSet 特点

  1. 元素唯一性;
  2. 可自定义排序;
  3. 不允许 null 存在;
  4. 不是线程安全。

2、自定义排序

  1. 类必须要实现一个接口 Comparable 才能做排序,之前所介绍的集合之所以没有顺序,就是因为此原因。

  2. Compare 比较两个字符串

    String str = "nbc";
    String str1 = "nbc";
    // 返回一个int类型的数字
    /*
    说明:两个字符串相互比较,从第一个字符开始比较相同索引的字符,如果第一个字符串的第一个字符比第二个字符串的第一
    个字符大(ASCII 码),就可以判断整个字符串比第二个字符串大;如果两个字符串的第一个字符相等,再去比较他们的第二个
    字符,同样遵守上述规律。
    */
    int val = str.compareTo(str1);
    System.out.println(val);

    ASCII 表
    Java系列(40)——集合(下)_数组_04
    Java系列(40)——集合(下)_数组_05

  3. compare 比较两个对象方法

    package cn.tx.set;

    public class Student implements Comparable<Student>
    {

    private int stuId;

    private String name;

    private int age;

    public int getStuId()
    {
    return stuId;
    }

    public void setStuId(int stuId)
    {
    this.stuId = stuId;
    }

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

    public Student(int stuId, String name, int age)
    {
    super();
    this.stuId = stuId;
    this.name = name;
    this.age = age;
    }

    /*
    实现比较两个学生对象的比较 :
    比较规则:
    1、先比较学号,按学号的升序排序 (o.stuId - this.stuId 为倒序 );
    2、如果学号相等,就按照年龄比较,年龄小的在前面;
    3、如果学号和年龄都相等,就按照名字的字符来比较。
    */
    @Override
    public int compareTo(Student o)
    {
    //先比较
    int val = this.stuId - o.stuId;
    if (val == 0)
    {
    val = this.age - o.age;
    if (val == 0)
    {
    if (this.name != null && o.name != null)
    {
    val = this.name.compareTo(o.name);
    }
    }
    }
    return val;
    }

    @Override
    public String toString()
    {
    return "Student [stuId=" + stuId + ", name=" + name + ", age=" + age + "]";
    }
    }
    Student s = new Student(2, "zhangsan", 34);
    Student s1 = new Student(2, "lisi", 34);

    int i = s.compareTo(s1);
    System.out.println(i > 0 ? "s大" : "s1大");

    Java系列(40)——集合(下)_数组_06

  4. TreeSet 示例

    // 创建一个TreeSet的集合
    Set<String> set = new TreeSet<String>();

    set.add("b");
    set.add("a");
    set.add("d");
    set.add("h");
    //按照 ASCII 码的大小进行排序
    System.out.println(set);

    Set<Integer> set1 = new TreeSet<Integer>();
    set1.add(23);
    set1.add(45);
    set1.add(2);
    set1.add(6);
    System.out.println(set1);

    Set<Student> set2 = new TreeSet<Student>();
    set2.add(new Student(2, "zhangsan", 23));
    set2.add(new Student(1, "zhangsan", 22));
    set2.add(new Student(3, "zhangsan", 56));
    set2.add(new Student(1, "ahangsan", 22));
    //按照 Student 类中我们规定的排序方式进行 Student 对象排序
    System.out.println(set2);

    Java系列(40)——集合(下)_java_07

五、可变参数

  1. J2SE 1.5 以后的版本中提供了 Varargs 机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递多个可变的实参。

  2. 可变参数的语法

    修饰符 返回值类型 方法名(数据类型…变量)
    {
    }
    public class DymanicParam
    {
    public static void main(String[] args)
    {
    int[] p = { 1, 2, 3, 4, 5 };
    int sum = add(p);
    System.out.println(sum);
    }

    public static int add(int a, int b)
    {
    return a + b;
    }

    public static int add(int a, int b, int c)
    {
    return a + b + c;
    }

    /**
    * 可变参数的定义
    *
    * int ... p 参数是一个int类型的数组,相当于int[] p
    */

    public static int add(int... p)
    {
    int sum = 0;
    for (int i = 0; i < p.length; i++)
    {
    sum += p[i];
    }
    return sum;
    }
    }

    Java系列(40)——集合(下)_数组_08

六、Arrays 工具类

  1. 数组的工具类,这里的方法都是静态的。
    Java系列(40)——集合(下)_数组_09

  2. toString 方法Java系列(40)——集合(下)_集合_10

  3. 把数组转换成字符串

    // int 类型数组
    int[] arr = { 12, 123, 55, 6 };
    System.out.println(Arrays.toString(arr));
    // 对象数组
    Student[] parr = { new Student(1, "张三", 23), new Student(1, "李四", 23) };
    System.out.println(Arrays.toString(parr));

    Java系列(40)——集合(下)_数组_11

  4. 对任意数组排序。
    (1)对 int 的数组做排序

    // 对 int 的数组做排序
    int[] arr = { 12, 123, 55, 6 };
    Arrays.sort(arr);
    System.out.println(Arrays.toString(arr));

    Java系列(40)——集合(下)_ide_12
    (2)对索引1到索引4进行排序

    int[] arr = { 12, 123, 55, 6 };   
    // 对索引1到索引4进行排序
    Arrays.sort(arr, 1, 4);
    System.out.println(Arrays.toString(arr));

    Java系列(40)——集合(下)_数组_13
    Java系列(40)——集合(下)_数组_14
    (3)对象排序

    Student[] parr = { new Student(2, "张三", 23), new Student(1, "李四", 23) };    
    System.out.println(Arrays.toString(parr));
    //排序规则是按照我们在Student类中所写的方法进行排序
    Arrays.sort(parr);
    System.out.println(Arrays.toString(parr));

    Java系列(40)——集合(下)_java_15

  5. 对任意的数组做二分法的查找。

    // 二分法的查找是必须有序的数组,所以需要先做排序
    int[] arr = { 6, 12, 123, 555, 666 };
    //二分法查找元素555,返回索引
    System.out.println(Arrays.binarySearch(arr, 555));

    Java系列(40)——集合(下)_ide_16

  6. 把数组转换成List

    // 定义一个数组
    Integer[] arr = { 6, 12, 123, 555, 666 };
    // 把数组转换成list
    List<Integer> iList = Arrays.asList(arr);
    System.out.println(iList);
    // 从数组转换过来的list不能添加和删除,修改可以
    // iList.add(34);
    // iList.remove(1);
    iList.set(2, 345);
    System.out.println(iList);

    Java系列(40)——集合(下)_字符串_17
    注意
    Java系列(40)——集合(下)_字符串_18

七、集合工具类

Java系列(40)——集合(下)_数组_19

  1. 示例源码

    package cn.tx.set;

    public class Emp
    {
    private int id;
    private int age;

    public Emp(int id, int age)
    {
    super();
    this.id = id;
    this.age = age;
    }

    public int getId()
    {
    return id;
    }

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

    public int getAge()
    {
    return age;
    }

    public void setAge(int age)
    {
    this.age = age;
    }

    @Override
    public String toString()
    {
    return "Emp [id=" + id + ", age=" + age + "]";
    }
    }
    package cn.tx.set;

    import java.util.Comparator;

    public class EmpComparator implements Comparator<Emp>
    {
    @Override
    public int compare(Emp e1, Emp e2)
    {
    int val = e1.getId() - e2.getId();
    if (val == 0)
    {
    val = e1.getAge() - e2.getAge();
    }
    return val;
    }
    }
    List<String> list = new ArrayList<String>();
    list.add("张三");
    list.add("李四");
    list.add("王五");
    list.add("赵六");
    list.add("田七");
    // 集合的反转
    Collections.reverse(list);
    System.out.println(list);
    // 随机打乱集合
    Collections.shuffle(list);
    System.out.println(list);

    // 排序
    List<String> list1 = new ArrayList<String>();
    list1.add("asd");
    list1.add("er");
    list1.add("tw");
    list1.add("qt");
    list1.add("gh");
    Collections.sort(list1);
    System.out.println(list1);

    List<Student> list2 = new ArrayList<Student>();
    list2.add(new Student(1, "zhangsan", 45));
    list2.add(new Student(4, "lisi", 42));
    list2.add(new Student(1, "wangwu", 12));
    Collections.sort(list2);
    System.out.println(list2);

    // 把list变成同步的(线程安全的)
    Collections.synchronizedList(list);

    // 对Emp排序,使用外部的比较器来做排序
    List<Emp> empList = new ArrayList<Emp>();
    empList.add(new Emp(5, 23));
    empList.add(new Emp(1, 24));
    empList.add(new Emp(1, 14));

    Collections.sort(empList, new EmpComparator());
    System.out.println(empList);

    Java系列(40)——集合(下)_数组_20

  2. 面试题
    问:Collection 和 Collections 的区别?
    答:前者是集合的接口;后者操作集合的工具类。

如有错误,欢迎指正!



举报

相关推荐

0 条评论