2019-01-01

作者: DreamPath | 来源:发表于2019-01-01 18:08 被阅读2次

    基于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<String> 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 集合数据存储结构是(双向)链表结构。

    图片.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<String> 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<String> 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)时,将链表转换为红黑树,这样大大减少了查找时间。
    图片.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<Student> 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<String> strings = new LinkedHashSet<>();
            //子类的实例父类的引用(多态)
            Set<String> 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 <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。
     * 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 class BiJiaoDemo {
        public static void main(String[] args) {
            List<Integer> 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<String> 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<String>() {
                @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<Student> 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<Student> 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<Student>() {
                @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

        本文链接:https://www.haomeiwen.com/subject/qliglqtx.html