Java-----Collection集合(hashSet,LinkedHashSet,treeSet,ArrayList,LinkedList)还有比较器的使用详解

集合

是Java提供的一种容器,可以用来存储多个数据。

与数组的区别:
①数组的长度固定,而集合的长度是可变的
②数组中存储的是同一类型的元素,可以存储基本数据类型,也可以存储对象;而集合存储的都是对象,不能存基本数据类型,但可以把基本数据类型转换成包装类存到集合中,而且对象的类型可以不一致

集合分类

1.单列集合(java.util.Collection)

2.双列集合(java.util.Map)

Collection类下结构图

在这里插入图片描述

Collection相关aip

Collection接口中定义着单列集合框架中最最共性的内容,也就是List和Set集合一些通用的方法,这些方法可操作所有的单列集合

1.int size():获取集合长度

2.boolean isEmpty():判断集合是否为空

3.void clear():清空集合

4.boolean contains(Object element):判断当前元素是否在集合内

5.boolean add(Object element):向集合中添加元素

6.boolean remove(Object element):根据参数删除集合中的元素

7.boolean containsAll(Collection c):判断一个集合中的元素是否存在于当前的集合中

8.boolean addAll(Collection c):向一个集合中添加另一个集合

9.boolean removeAll(Collection c):在一个集合中删除参数指定的集合

10.boolean retionAll(Collection c):获取两个集合的交集

11.object[] toArray:把一个集合转换为Object数组

Set接口

1.简介:java.util.Set和java.util.List接口一样,都继承Collection接口,它与Collection接口中的方法基本一致,并没有进行功能上的扩充,只是比Collection接口更加严格了,与List接口不同的是,Set接口中元素无序,并且会已以某种规则保证存入的元素不重复。Set集合取出元素不可以用普通for循环,因为Set集合没有索引,可以采用迭代器或者增强for进行遍历。

HashSet实现类

用hash技术实现的Set结构,也具备集合中元素不能重复这一特性。

1.存入自定义类的时候HashSet如何检查重复:它会根据hashCode来判断对象加入的位置,同时也会与其它已经加入的对象的hashCode进行比较,如果没有相等的hashCode,HashSet就会假设对象没有重复;如果hashCode值相同,会继续使用equals进行比较,如果equals为true,那么认为对象重复了,加入失败。如果为false,那么认为加入的对象没有重复,可以加入。所以我们在自定义类的时候需要重写hsahCode,还要重写equals方法

2.为什么要重写hashCode:因为如果使用Object提供的hashCode方法,他会根据不同的对象生成不同的整数,所以只要创建了不同的对象,hashCode的值是不同的,但如果里面的内容相同,我们就会在集合中存入两个相同内容的元素。为了解决这个问题,我们要重写hashCode方法,让对象具有相同的hashCode值。

 @Override
 //一般使用idea提供的重写好的hashCode方法,会和equals方法一起重写
    public int hashCode() {
        return Objects.hash(id, name);
    }

3.为什么要重写equals:因为equals比较的是地址,不同对象的地址是不相同的,我们比较的都是内容是否相等,所以想要比较两个对象是否相等,就要重写equals方法,让他按照自己定义的比较方式进行比较两个对象是否相等(一般是比较对象的内容相等)。

@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student1 student1 = (Student1) o;
        //如果id和name都相等,那么两个对象是相同元素
        return id == student1.id &&
        Objects.equals(name, student1.name);
    }

4.当hashCode值相同,equals为false时,元素如何存储?
在同样的哈希值下顺延(放入下一个位置),会用到散列技术等。或者用数组+链表实现;JDK1.8哈希表使用数组加链表加红黑树,当链表长度大于8时,就将链表转换成红黑树,来减少查找到时间。

5.HashSet中存入基本数据类型

		//泛型使用基本数据类型的包装类
        HashSet<Integer> i = new HashSet<>();
        //添加元素
        i.add(1);
        i.add(2);
        System.out.println(i);

6.自定义类型存入HashSet(要在自定义类中重写hashCode和equals方法)

public class Student1 {
    private int id;
    private String name;

    public Student1() {
    }

    public Student1(int id, String name) {
        this.id = id;
        this.name = name;
    }

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

    @Override
    public String toString() {
        return "Student1{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student1 student1 = (Student1) o;
        return id == student1.id &&
                Objects.equals(name, student1.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
}

public static void main(String[] args) {
        //创建集合对象   该集合中存储 Student1类型对象
        HashSet<Student1> stuSet = new HashSet<Student1>();
        //存储 
        Student1 stu = new Student1("张三", 22);
        stuSet.add(stu);
        stuSet.add(new Student("李四", 44));
        stuSet.add(new Student("张三", 22));
        System.out.println(stuSet);//只会存入两个对象
    }
LinkedHashSet实现类

因为HashSet保证了元素的唯一,但是元素的存放是无序的,如果我们要保证有序,就要使用LinkedHashSet,他是链表和哈希表组合的一个数据存储结构

public static void main(String[] args) {
        //特点是存取有序
        Set<String> set = new LinkedHashSet<String>();
        set.add("aaa");
        set.add("bbb");
        set.add("ccc");
        set.add("ddd");
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());//会按顺序打印
        }
    }
TreeSet实现类

是一个可排序集合,基于红黑树(自平衡二叉树),默认按元素自然顺序升序排列

1.数值类排序

 TreeSet<Integer> t = new TreeSet<>();
    t.add(3);
    t.add(2);
    t.add(5);
    t.add(1);
    t.add(2);
    System.out.println(t);//1, 2, 3, 5

2.字符串形式也可排序,会按照第一个字符的升序排列,如果第一个字符相同,按照第二个字符,以此类推。

3.自定义类排序需要使用比较器

比较器

1.Comparable接口:继承接口后在类中重写compareTo方法,让元素自身具备比较性。此接口强行对实现他的每个类的对象进行整体排序,这种排序被称为类的自然排序,类的compareTo方法被称为他的自然比较方法。在创建完该类对象的TreeSet集合后,会自动进行排序。

public class Student implements Comparable<Student> {
    private int id;
    private String name;

    public Student() {
    }

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return id == student.id &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }

    @Override
    public int compareTo(Student o) {
        //this 和 参数 o比较
        //this>stu  (升序排列)
        //this<stu  (降序排列)
        //this等于stu   返回0

        //按照id升序排列
        // return this.id-o.getId();
        //按照id降序排列
        // return o.getId()-this.id;

        //如果年龄相等的情况下,按照姓名升序排列
        int x=this.id-o.getId();
        if(x==0){
            //按照姓名排序,String内部已经重写ComparTo的方法,这个方法直接返回一个整数
            return this.name.compareTo(o.getName());
        }else{
            return x;
        }

    }
}

public class Comparable {
    public static void main(String[] args) {
        TreeSet<Student> stu = new TreeSet<>();
        stu.add(new Student(1,"张三"));
        stu.add(new Student(4,"李四"));
        stu.add(new Student(2,"王五"));
        stu.add(new Student(2,"张三"));

        //如果按照一个字段进行排序的时候,当前字段在容器中有多个重复的值,那么会认为是重复性元素,只展示一个

        //否则如果多个元素作为衡量标准,只要多个元素不重复,就会进行排序。
        for(Student s:stu){
            System.out.println(s);
        }
    }
}

2.Comparator接口:元素自身不具备比较性,而让装对象的容器具有比较性。强行对某个对象collection进行整体排序的比较函数。可以将Comparator传递给sort方法(如Collections.sort或Arrays.sort),从而允许在排序顺序上实现精准控制。

①定义一个类实现Comparator接口,重写compare方法,并将该接口的子类对象作为参数传递给TreeSet集合的构造方法。

public class CompareCollection implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        //按照id升序排列,排序规则和Comparabla的规则一样
        return o1.getId()-o2.getId();
    }
}

public class Comparator {
    public static void main(String[] args) {
        Set<Student> stu = new TreeSet<>(new CompareCollection());
        stu.add(new Student(1,"张三"));
        stu.add(new Student(4,"李四"));
        stu.add(new Student(2,"王五"));
        stu.add(new Student(2,"张三"));
        System.out.println(stu);
    }
}

如果对象自身具备比较性,同时容器也具备比较性,那么按照容器的比较性进行比较。

②定义一个类实现Comparator接口,重写compare方法,并将该接口的子类对象作为参数传递给集合的sort方法。

//实现Comparator接口的类同上
public static void main(String[] args) {
        List<Student> o = new ArrayList<>();
        o.add(new Student(1,"张三"));
        o.add(new Student(4,"李四"));
        o.add(new Student(2,"王五"));
        o.add(new Student(2,"张三"));
        o.sort(new CompareCollection());
        for(Student s:o){
            System.out.println(s);
        }
    }

List接口

1.List接口的容器类中的元素是有顺序的,而且可以重复,每一个元素都对应一个在容器中位置的序号。

2.List接口中扩展的方法:
①Object get(int index):通过索引获取元素

②Object set(int index,Object element):修改索引出元素

③void add(int index,Object element):在某处索引添加元素

④Object remove(int index):根据索引删除元素

ArrayList实现类

集合数据存储的结构是数组结构,元素增删慢,查找快,因为日常开发中使用最多的功能为查询数据,遍历数据,所以ArrayList是最常用的集合。

LinkedList实现类

集合数据存储的结构是链表结构,方便元素添加,删除。LinkedList是一个双向链表,在添加和删除操作时会涉及到首尾操作。

常用的方法:
①public void addFirst(E e):将指定元素插入此列表的开头

②public void addLast(E e):将指定元素添加到此列表的结尾

③public E getFirst():返回此列表中的第一个元素

④public E getLast():返回此列表中的最后一个元素

⑤public E removeFirst():移除并返回此列表的第一个元素

⑥public E removeLast():移除并返回此列表的最后一个元素

⑦public boolean isEmpty():如果列表不包含元素,则返回truet

ArrayList与LinkedList的区别

1.他们都是线性表,但ArrayList基于数组(顺序存储),LinkedList基于链表(链式存储)

2.由于实现的不同,ArrayList在随机访问元素时性能较高,插入和删除元素时效率较低,LinkedList则反之。

Vector

描述的是一个线程安全的ArrayList。

1.Vector与ArrayList的区别:
ArrayList:多线程效率高
Vector:多线程安全的,所以效率低

2.常用方法:
①void addElement(E obj):在集合末尾添加元素

②E elementAt(int index):返回指定角标的元素

③Enumeration elements():返回集合中的所有元素,封装到Enumeration对象中

Enumeration接口

①boolean hashMoreElements():测试此枚举是否包含更多元素

②E nextElement():如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。

Stack(栈)

Stack类是Vector类的子类,特点是先进后出。

1.常用方法:
①empty():测试堆栈是否为空

②peek():查看堆栈顶部的对象,但不从堆栈中移除他

③pop():移除堆栈顶部的对象,并返回该对象作为此函数的值

④push(E item):把项压入堆栈顶部

⑤int search(Object o):返回对象在堆栈中的位置,以1为基数

操作集合的工具类Collections

用来对集合进行操作

常用方法:
1.sort(List<> list):对List进行默认排序
sort(List<> list,new Comparator(){}):在sort中加入排序器,可以让自定义元素进行排序。

2.addAll(Collection<T>,T…e):向集合中添加可变参数元素

3.fill(List<E> list,E e):将list集合中的所有元素都填充为元素e

4.int frequency(Collection<E> c,E e):返回在集合c中的元素e的个数

5.max,min:获取集合的最大值或者最小值

6.replaceAll(List<E> list, E oldVal, E newVal):将集合list中的所有指定老元素oldVal都替换成新元素newVal

7.reverse(List<E> list):将参数集合list进行反转

8.shuffle(List<E> list):将list集合中的元素进行随机置换

9.swap(List<E> list, int a, int b):将a索引和b索引的元素进行交换

10.synchronizedXxx方法系列:将一个线程不安全的集合传入方法,返回一个线程安全的集合

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值