2019-01-01

基于List、Set集合,及工具类Collections集合元素排序整理

List集合

1.1 List集合介绍

java.util.List 接口继承自 Collection 接口,是单列集合的一个重要分支。

  • 存储形式:线性存储

  • 集合特点

  1. 元素存取有序。
  2. 带索引,通过索引就可操作元素。
  3. 元素可重复。
1.2 List集合常用方法
  • public void add(int index, E element) : 将指定的元素,添加到该集合中的指定位置上。
  • public E get(int index) :返回集合中指定位置的元素。
  • public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。
  • public E set(int index, E element) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
package list_demo;

import java.util.ArrayList;
import java.util.List;

/**
 * @author lx
 * @date 2018/12/30 - 13:12
 * public void add(int index, E element) : 将指定的元素,添加到该集合中的指定位置上。
 * public E get(int index) :返回集合中指定位置的元素。
 * public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。
 * public E set(int index, E element) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素
 */
public class List_Demo {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add("Hello");
        list.add("World");
        list.add("Hello World");
        // 在索引为1的位置添加元素"你好"
        list.add(1, "你好");

        System.out.println(list);//[Hello, 你好, World, Hello World]
        // 返回集合中指定位置的元素。
        System.out.println(list.get(2));//World
        //删除元素(通过内容,通过索引)
        list.remove("Hello");
//     list.remove(0);
        System.out.println(list);//[你好, World, Hello World]
//      在指定索引处替换元素
        list.set(2, "你好世界");
        System.out.println(list);//[你好, World, 你好世界]
    }
}

List的子类

ArrayList集合

java.util.ArrayList 集合数据存储的结构是数组结构。

  • 特点:
    元素增删慢,查找快。
    多用于查询数据,遍历数组
LinkedList集合

java.util.LinkedList 集合数据存储结构是(双向)链表结构。

2019-01-01_第1张图片
图片.png
  • LinkedList常用方法及其用法
package list_demo;

import java.util.LinkedList;

/**
 * @author lx
 * @date 2018/12/30 - 13:33
 * 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
 */
public class List_demo1 {
    public static void main(String[] args) {
        LinkedList strings = new LinkedList<>();
        strings.add("赵丽颖");
        strings.add("冯绍峰");
        strings.add("李连杰");
        System.out.println(strings);//[赵丽颖, 冯绍峰, 李连杰]----
        //在首尾添加元素
        strings.addFirst("马云");
        strings.addLast("甑子丹");
        System.out.println(strings);//[马云, 赵丽颖, 冯绍峰, 李连杰, 甑子丹]
        //直接获取首尾元素
        System.out.println(strings.getFirst());//马云
        System.out.println(strings.getLast());//甑子丹
        //删除首尾元素
        strings.removeFirst();
        strings.removeLast();
        System.out.println(strings);//[赵丽颖, 冯绍峰, 李连杰]
        //弹出集合的栈顶元素。(弹栈)打子弹(先打出弹夹上第一个)
        String pop = strings.pop();

        System.out.println(pop);//赵丽颖
        System.out.println(strings);//[冯绍峰, 李连杰]
        //将元素推入此列表所表示的堆栈。(压栈存储)放弹夹
        strings.push("赵丽颖");
        System.out.println(strings);//[赵丽颖, 冯绍峰, 李连杰]
        //判断集合中是否含有元素
        System.out.println(strings.isEmpty());//false
    }
}

Set接口

Set集合的定义

java.util.Set 接口继承自 Collection 接口,只是其中的方法比 Collection 接口更加严格了。

Set 集合特点:
   1.无序、不可重复(存储数据唯一,
                   原因:底层使用了数组加链表的形式存储数据)。
   2.查询快,增删快(jdk1.8以后)。
Set接口的子类
  • Set 集合的常用子类java.util.HashSet 、 java.util.LinkedHashSet。
HashSet集合

java.util.HashSet 是 Set 接口的一个实现类,它所存储元素是不可重复的,元素都是无序的(即存取顺序不一致)。

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

import java.util.HashSet;
/**
 * @author lx
 * @date 2018/12/30 - 21:42
 */
public class HashSetDemo {
    public static void main(String[] args) {
//        创建HashSet集合
        HashSet str = new HashSet<>();
        //添加元素
        str.add("刘备");
        str.add("张飞");
        str.add("关羽");
        str.add("刘备");//不可重复
        //输出集合
        System.out.println(str);//[关羽, 张飞, 刘备]    无序排列
    }
}
HashSet集合存储数据的结构(哈希表)
  • 1.在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。
  • 2.但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。查找速度过慢。
  • 3.而在JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
2019-01-01_第2张图片
图片.png
  • JDK1.8引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一, 其实就是根据对象的hashCode和equals方法来决定的。
  • 如果我们往集合中存放自定义的对象,那么保证其唯一, 就必须复写hashCode和equals方法建立属于当前对象的比较方式。
HashSet存储自定义类型元素
  • HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一。
  • 自定义Student类
package set_demo;

import java.util.Objects;

/**
 * @author lx
 * @date 2018/12/31 - 11:34
 */
public class Student {
    private String name;
    private int age;
    private int id;
 //  无参构造方法
    public Student(){
    }
//有参构造方法
    public Student(String name, int age, int id) {
        this.name = name;
        this.age = age;
        this.id = id;
    }
//setter,getter方法
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getAge() {
        return age;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getId() {
        return id;
    }
    //重写equals方法和hashCode方法
    @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 &&
                id == student.id &&
                Objects.equals(name, student.name);
    }@Override
    public int hashCode() {
        return Objects.hash(name, age, id);
    }
//    重写toString方法
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", id=" + id +
                '}';
    }
}
  • 创建一个测试类
package set_demo;

import java.util.HashSet;

/**
 * @author lx
 * @date 2018/12/31 - 11:39
 */
public class HashSet_demo1 {
    public static void main(String[] args) {
        HashSet strings = new HashSet<>();
        Student student = new Student("梦雨", 19, 1000);
        strings.add(student);
        //使用匿名对象
        strings.add(new Student("小明", 22, 1001));
        strings.add(new Student("小雪", 18, 1002));
        strings.add(new Student("梦雨", 19, 1000));
        //由于重写了toString方法,因此可以直接输出
        System.out.println(strings);
        //输出结果如下,,明显看出是无序的,不可重复的。
        //[Student{name='小明', age=22, id=1001}, 
        // Student{name='小雪', age=18, id=1002},
        // Student{name='梦雨', age=19, id=1000}]
    }
}
2.3 LinkedHashSet集合
  • java.util.LinkedHashSet 是HashSet的一个子类。
    也能保证元素的唯一性(不可重复)。
  • 而它的数据存储结构链表和哈希表组合而成的。因此是有序的。
package set_demo;
import java.util.LinkedHashSet;
/**
 * @author lx
 * @date 2018/12/31 - 11:59
 */
public class LinkedHashSetDemo {
    public static void main(String[] args) {
        LinkedHashSet strings = new LinkedHashSet<>();
        //子类的实例父类的引用(多态)
        Set strings1=new LinkedHashSet<>();
        strings.add("杨幂");
        strings.add("刘恺威");
        strings.add("胡歌");
        strings.add("霍建华");
        strings.add("杨幂");
        System.out.println(strings);
        /*
        输出结果为:[杨幂, 刘恺威, 胡歌, 霍建华]
        可以看出集合是有序,不可重复的。
         */
    }
}
可变参数
  • 在JDK1.5之后,如果我们定义一个类型一致的多个参数时,定义规则为:

    • 修饰符 返回值类型 方法名(参数类型... 形参名){ }<==>修饰符 返回值类型 方法名(参数类型[] 形参名){ }.
  • 后面这种方式需要传递数组才能完成值传递,而前者只需要直接传递数据即可。

  • 可变参数:调用时不创建数组,直接将数组元素传递。

  • 编译生成.class文件前直接就将这些元素封装成一个数组,然后再进行传递。

package kebian_CanShu;

/**
 * @author lx
 * @date 2019/1/1 - 1:24
 */
public class KebianCanShuDemo {
    public static void main(String[] args) {
        //数组传递
        int[] aInt = {1, 2, 3, 4, 5};
        int sum=getSum(aInt);
        System.out.println(sum);//15
        //可变参数 数据值传递
        int sum2 = getSum(1,2,4,5,6,7);
        System.out.println(sum2);//25

    }
    //使用可变参数语法:    数据类型  ...   数组名
    private static int getSum(int... aInt) {
        int sum2 = 0;
        for (int s : aInt) {
            sum2 += s;
        }
        return sum2;
    }
/*  一般数组传递
  private static int getSum(int[] aInt) {
        int sum = 0;
        for(int a : aInt){
            sum += a;
        }
        return sum;

    }*/
}

Collections 工具类

常用方法

package biJiao;
import java.util.*;

/**
 * @author lx
 * @date 2019/1/1 - 11:44
 * java.utils.Collections 是集合工具类,用来对集合进行操作。部分方法如下:
 * public static  boolean addAll(Collection c, T... elements) :往集合中添加一些元素。
 * public static void shuffle(List list) 打乱顺序 :打乱集合顺序。
 * public static  void sort(List list) :将集合中元素按照默认规则排序。
 * public static  void sort(List list,Comparator ) :将集合中元素按照指定规则排序
 */
public class BiJiaoDemo {
    public static void main(String[] args) {
        List list = new ArrayList();
       /* list.add(22);
        list.add(20);
        list.add(17);
        list.add(22);
        System.out.println(list);*/
        //采用工具类 完成 往集合中添加元素
        Collections.addAll(list, 2, 5, 6, 7, 9);
//                打乱集合元素顺序
        Collections.shuffle(list);
        System.out.println(list);//[7, 5, 2, 6, 9]
        //将集合中的元素按照默认规则排序(默认升序)
        Collections.sort(list);
        System.out.println(list);//[2, 5, 6, 7, 9]
    }
}
  • 字符串默认排序及其自定义排序
package biJiao;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

/**
 * @author lx
 * @date 2019/1/1 - 13:17
 */
public class BiJiaoDemo2 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList<>();
        list.add("sba");
        list.add("aba");
        list.add("bbd");
        list.add("cer");
        list.add("bar");
        System.out.println(list);//[sba, aba, bbd, cer, bar]
        //字符串默认排序是以首写字母排序的.
        // 如果首写字母相同,则比较下一位,按照字母升序排列
        Collections.sort(list);
        System.out.println(list);//[aba, bar, bbd, cer, sba]
        //按照字母降序排序
        Collections.sort(list, new Comparator() {
            @Override
            public int compare(String o1, String o2) {
                return  o2.charAt(0)-o1.charAt(0);
            }
        });
        System.out.println(list);//[sba, cer, bar, bbd, aba]
    }
}

Comparable和Comparator两个接口的区别

Comparable:
  • 1.将它的实现类的对象强制进行整体排序,并在类中重写一次compareTo方法。
  • 2.不能经常修改类中的代码来实现想要的排序。
  • 3.实现此接口的对象列表或者数组可通过Collections.sort()或者Arrays.sort()进行自动排序。
  • 4.对象可以用作有序映射中 的键或有序集合中的元素,无需指定比较器。
Comparator:
  • 1.强行对某个对象进行整体排序。

  • 2.可以将Comparator 传递给工具类中的sort方法,从而允许在排序顺序上实现精确控制。

  • 3.使用Comparator来控制某些数据结构(如有序set或 有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。

方法一:采用实现comparable接口

创建一个学生类,存储到ArrayList集合中完成指定排序操作。

package biJiao;

public class Student implements Comparable{
    private String name;
    private int  age;

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", 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//返回0  相等  正数  降序排列 负数 升序排列
    public int compareTo(Object o) {
        Student o1 = (Student) o;
        return (getAge()-o1.getAge())*(-1);
    }
}
创建测试类
package biJiao;

import java.util.ArrayList;
import java.util.Collections;

/**
 * @author lx
 * @date 2019/1/1 - 15:04
 */
public class Student_demo {
    public static void main(String[] args) {
//创建集合
        ArrayList list = new ArrayList<>();
//添加元素
        list.add(new Student("马云", 30));
        list.add(new Student("宋小宝", 34));
        list.add(new Student("宋人喜", 33));
        list.add(new Student("史玉柱", 29));
//根据Student类的年龄降序排序
        Collections.sort(list);
        System.out.println(list);        //输出结果如下
        //[Student{name='宋小宝', age=34},Student{name='宋人喜', age=33},
        //Student{name='马云', age=30}, Student{name='史玉柱', age=29}]
    }
}

方法二:采用new Comparator实现

  • Student类中只需要不用再实现Comparable接口,也就不用重写compareTo方法
    测试类
package biJiao;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

/**
 * @author lx
 * @date 2019/1/1 - 15:04
 */
public class Student_demo {
    public static void main(String[] args) {

        ArrayList list = new ArrayList<>();

        list.add(new Student("马云", 30));
        list.add(new Student("宋小宝", 34));
        list.add(new Student("宋人喜", 33));
        list.add(new Student("史玉柱", 30));
        //sort方法下做如下改动,Student类中,不再实现comparable接口并不重写compareTo方法
        Collections.sort(list, new Comparator() {
            @Override
            public int compare(Student o1, Student o2) {
                //年龄降序
               int result=o2.getAge()-o1.getAge();
               //如果年龄相同,按照名字首写字母降序
                if (o1.getAge()==o2.getAge()) {
                  result= o1.getName().charAt(0)-o2.getName().charAt(0);
                }
                return  result;
            }
        });
        System.out.println(list);        //输出结果如下   s    m
        //[Student{name='宋小宝', age=34}, Student{name='宋人喜', age=33},
        // Student{name='史玉柱', age=30}, Student{name='马云', age=30}]
    }
}

你可能感兴趣的:(2019-01-01)