java之List集合介绍及其实现类,Set集合介绍及其实现类,Collections集合工具类(包含了用来操作集合的各种方法)

目录

 List集合

List接口的特点:

List接口中常用方法:

List集合遍历有三种遍历方式:

ArrayList集合

LinkedList集合

Vector集合

Set集合

Set接口中元素的特点:

HashSet集合

HashSet集合存储数据的结构(哈希表)

Set集合存储元素不重复的原理:

LinkedHashSet集合

Collections集合工具类(操作集合的各种方法,全是静态方法。相对应的,操作数组的各种方法为Arrays工具类)



 List集合

List接口介绍:

java.util.List接口  extends  Collection接口,是单列集合的一个重要分支,习惯性地会将实现了List接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。

List接口的特点:

  1. 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。

  2. 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。

  3. 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。

tips:我们在基础班的时候已经学习过List接口的子类java.util.ArrayList类,该类中的方法都是来自List中定义。

List接口中常用方法:

List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法,如下:

  • public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。

  • public E get(int index):返回集合中指定位置的元素。

  • public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。

  • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回被替换的元素。

注意:操作索引的时候,一定要防止索引越界异常。编译报错,运行报错。

List集合遍历有三种遍历方式:

1.使用普通for循环。

2.使用迭代器。

3.使用增强for循环。

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
public class ListFor {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("迪丽热巴");
        list.add("古力娜扎");
        list.add("赵丽颖");
        list.add("杨颖");
        String remove = list.remove(3);
        String get = list.get(0);
        String setName = list.set(2, "麦迪娜");
        System.out.println("删除的是:"+remove+" 第一个是:"+get+" 被替换的是:"+setName);
        System.out.println("最新角逐名单:"+list);
        // 三种循环方式
        System.out.println("方式一:使用普通for循环");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        System.out.println("方式二:使用Iterator");
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String next = it.next();
            System.out.println(next);
        }
        System.out.println("方式三:使用增强型for");
        for (String s : list) {
            System.out.println(s);
        }
    }
}

ArrayList集合

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

许多程序员开发时非常随意地使用ArrayList完成任何需求(应该查询多的时候使用该集合,增删多的时候不应该使用该集合),并不严谨,这种用法是不提倡的。

LinkedList集合

java.util.LinkedList集合数据存储的结构是链表结构。方便元素添加、删除的集合。

LinkedList是List的子类,List中的方法LinkedList都是可以使用,这里就不做详细介绍,我们只需要了解LinkedList的特有方法即可。在开发时,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 E pop():从此列表所表示的堆栈处弹出一个元素。

  • public void push(E e):将元素推入此列表所表示的堆栈。

  • public boolean isEmpty():如果列表不包含元素,则返回true。

Vector集合

Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。与新 collection 实现不同,Vector同步的。也就是单线程的,这是早期的1.0版本的。

Set集合

介绍:

java.util.Set接口和java.util.List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格了。

Set接口中元素的特点:

List接口不同的是

(1)没有索引,没有带索引的方法,因此不能使用普通的for循环遍历。

(2)不允许出现重复。

Set集合有多个子类,这里我们介绍其中的java.util.HashSetjava.util.LinkedHashSet这两个集合。

tips:Set集合取出元素的方式可以采用:迭代器、增强for。

HashSet集合

java.util.HashSet集合  implements  Set接口,是一个实现类。

HashSet集合特点:

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

2.不允许出现重复元素。

3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致。

4.底层是一个哈希表结构(java.util.HashMap支持查询速度非常快

HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCodeequals方法。

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetTest {
    public static void main(String[] args) {
        Set<Integer> list = new HashSet<>();
        list.add(10);
        list.add(30);
        list.add(20);
        list.add(10);  // 重复元素
        // 使用迭代器
        Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()){
            Integer next = iterator.next();
            System.out.println(next); // 20 10 30 无序
        }
        // 使用增强for
        for (Integer integer : list) {
            System.out.println(integer); // 20 10 30无序
        }
    }
}

HashSet集合存储数据的结构(哈希表

哈希值:是一个十进制的整数,由操作系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到的地址,不是数据实际存储的物理地址)。

在Object类有一个方法,可以获取对象的哈希值。int hashCode()方法

哈希冲突:元素不同,但是哈希值相同。

哈希表:

JDK1.8之前,哈希表底层采用数组+链表实现。数组结构将元素进行了分组,相同哈希值的元素是一组,放在同一个哈希值下面。因为数组存储的是哈希值。然后使用链表处理哈希冲突,同一hash值的链表都存储在一个链表里。但是当位于一个链表中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。

简单的来说

jdk1.8版本之前:哈希表 = 数组 + 链表

jdk1.8版本之后:哈希表 = 数组 + 红黑树

哈希表的特点:速度快!

Set集合存储元素不重复的原理:

HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCodeequals方法。

存储流程图:

HashSet存储自定义类型元素

给HashSet中存放自定义类型元素时,一定需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一 。

// 自定义数据类型Student,一定要重写equals和hashCode方法
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(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;
    }
    // 重写了equals方法
    @Override  
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        Student student = (Student) o;
        return age == student.age &&
               Objects.equals(name, student.name);
    }
    // 重写了hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
// 测试存储自定义类型数据,能使得结果不重复。
public class HashSetDemo2 {
    public static void main(String[] args) {
        //创建集合对象   该集合中存储 Student类型对象
        HashSet<Student> stuSet = new HashSet<Student>();
        //存储 
        Student stu = new Student("于谦", 43);
        stuSet.add(stu);
        stuSet.add(new Student("郭德纲", 44));
        stuSet.add(new Student("于谦", 43));
        stuSet.add(new Student("郭麒麟", 23));
        stuSet.add(stu);

        for (Student stu2 : stuSet) {
            System.out.println(stu2);
        }
    }
}
执行结果: // 不会重复于谦
Student [name=郭德纲, age=44]
Student [name=于谦, age=43]
Student [name=郭麒麟, age=23]

LinkedHashSet集合

java.util.LinkedHashSet集合  extends  HashSet集合

LinkedHashSet集合特点:

底层是一个哈希表(数组+链表/红黑树)+链表。多了一条链表是为了记录元素的存储顺序,保证元素有序

import java.util.HashSet;
import java.util.LinkedHashSet;
public class LinkedHashSetTest {
    public static void main(String[] args) {
        // 使用HashSet集合 
        HashSet<String> set = new HashSet<>();
        set.add("古力娜扎");
        set.add("赵丽颖");
        set.add("迪丽热巴");
        set.add("迪丽热巴");
        System.out.println(set); // [赵丽颖, 迪丽热巴, 古力娜扎] 存储是无序的
        // 使用LinkedHashSet集合 
        LinkedHashSet<String> linedSet = new LinkedHashSet<>();
        linedSet.add("古力娜扎");
        linedSet.add("赵丽颖");
        linedSet.add("迪丽热巴");
        linedSet.add("迪丽热巴");
        System.out.println(linedSet); // [古力娜扎, 赵丽颖, 迪丽热巴] 存储是有序的
    }
}

Collections集合工具类(操作集合的各种方法,全是静态方法。相对应的,操作数组的各种方法为Arrays工具类

java.utils.Collections集合工具类,用来对集合进行操作。部分方法如下:

  • public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加多个元素,不用像之前的一个一个add添加进集合中了。

  • public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。

  • public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。

  • public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。

public static <T> void sort(List<T> list)方法使用前提:

被排序的list集合里面存储的元素,必须实现Comparable接口,重写接口中的compareTo方法定义排序的规则。

排序规则:通常规定,对于两个元素xy,原来的顺序是x在前y在后。如果认为x < y,则返回-1,如果认为x == y,则返回0,如果认为x > y,则返回1,这样,排序算法就不用关心具体的比较过程,而是根据比较结果直接排序。

  • 返回1,表示前后两个相邻元素要换位置,-1和0不换。比如:如果x = 10 ,y = 5 x > y return 1。当x>y的时候要交换位置,那么就是升序排序。

  • 如果x = 10,y = 20 y > x return 1.表示当y>x的时候要交换位置,那么表示降序排序。

this.age永远是当前的元素,o.age是下一个元素。当为正的时候,即return 1.需要交换顺序。其余情况则不需要交换顺序。

通过上面的规则:

当 this.age>o.age时,年龄按升序排序。 所以当return this.age-o.age时,年龄升序排序。 

当 this.age<o.age时,年龄按降序排序 。 所以当return o.age-this.age时,年龄降序排序

Comparator和Comparable的区别,也就是方法三和方法四的区别:

Comparable:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较规则compareTo方法。

Comparator:相当于找一个第三方的裁判,比较两个,里面的参数原来的顺序是o1在前o2在后。

// 定义一个Person类,其中重写了toString方法,实现Comparable接口并重写compareTo方法
public class Person implements Comparable<Person> {
    private String name;
    private int age;
    private int nice;  // 美貌值 0-10
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", nice=" + nice +
                '}';
    }
    public Person() {
    }
    public Person(String name, int age, int nice) {
        this.name = name;
        this.age = age;
        this.nice = nice;
    }
    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 int getNice() {
        return nice;
    }
    public void setNice(int nice) {
        this.nice = nice;
    }
    @Override  // 如果没有重写该方法就不能对Person排序。
    public int compareTo(Person o) {
//        return 0; //原来的代码恒返回0,表示不需要交换未知也就是不进行排序返回原序列。
        if (this.age > o.age) {  // 只对年龄进行了排序
            return 1;  // 返回正序。原来的顺序:this.age是当前元素,o.age是下一个元素。return 1需要交换位置。
        }
        if (this.age < o.age) {
            return -1;
        }
        return 0;
        // 等效于下面这句
//        return this.age-o.age;  // this.age永远是当前的元素,o.age是下一个元素。当为正的时候,即return 1.需要交换顺序。其余情况则不需要交换顺序。
        /* 当 this.age>o.age时,年龄按升序排序。
           所以return this.age-o.age时,年龄升序排序。
           当 this.age<o.age时,年龄按降序排序
           所以当return o.age-this.age时,年龄降序排序。
        */
    }
}
// Collections集合工具类的使用
import java.util.Collections;
import java.util.Comparator;
import java.util.ArrayList;
import java.util.List;
public class LinkedHashSetTest {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list,10,23,11,5); // 一次加入多个元素,这个可以Collection集合,不局限于List集合
        System.out.println(list); // [10, 23, 11, 5]
        Collections.sort(list);  // 默认规则排序,从小到大
        System.out.println(list); // 升序 [5, 10, 11, 23]
        // 使用第三方规则
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1; // 第三方规则,从大到小
            }
        });
        System.out.println(list); // 降序 [23, 11, 10, 5]
        Collections.shuffle(list); // 打乱顺序
        System.out.println(list); // [11, 23, 5, 10]

        // List集合中的元素是自定义类型
        List<Person> persons = new ArrayList<>();
        persons.add(new Person("赵丽颖",20,7));
        persons.add(new Person("迪丽热巴",18,9));
        persons.add(new Person("古力娜扎",19,8));
        // 被排序的list集合里面存储的元素,必须实现Comparable接口,重写接口中的compareTo方法定义排序的规则。
        Collections.sort(persons); // 进行排序,排序规则已经重写,只对年龄排序,是升序排序。
        System.out.println(persons); // [Person{name='迪丽热巴', age=18, nice=9}, Person{name='古力娜扎', age=19, nice=8}, Person{name='赵丽颖', age=20, nice=7}]
        // 还可以使用第三方的,不需要去继承Comparable类和重写compareTo方法
        Collections.sort(persons, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getNice()-o2.getNice();// 美貌值从小到大排序
            }
        });
        System.out.println(persons); // [Person{name='赵丽颖', age=20, nice=7}, Person{name='古力娜扎', age=19, nice=8}, Person{name='迪丽热巴', age=18, nice=9}]
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值