• Java集合框架(二)


       Set

       Set:无序,不可以重复元素。

      |--------HashSet:数据结构是哈希表。

          线程是非同步的。保证元素唯一性的原理是:判断元素的hashCode值是否相同,如果相同,还会继续判断元素的equals方法,是否为true

      |--------TreeSet:可以对Set集合中元素进行排序。

           底层数据结构是二叉树(也叫红黑树),保证元素唯一性的依据是:compareTo()方法return 0。

          TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo()方法。这种方式也称为元素的自然顺序,或者也叫默认顺序。

          TreeSet排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的,这是就需要让集合自身具备比较性。在集合一初始化时,就具备比较方式。

       例,需求:往TreeSet集合中存储自定义对象学生。想按照学生的年龄进行排序。

       int compareTo(T o):比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

       代码如下:

    import java.util.Iterator;
    import java.util.TreeSet;
    
    public class TreeSetDemo {
    
        public static void sop(Object obj) {
            System.out.println(obj);
        }
        
        public static void main(String[] args) {
            TreeSet ts = new TreeSet();
            
            ts.add(new Student("lisi02", 22));
            ts.add(new Student("lisi007", 20));
            ts.add(new Student("lisi09", 19));
            ts.add(new Student("lisi08", 19));
            //ts.add(new Student("lisi02", 22));
            
            Iterator it = ts.iterator();
            
            while(it.hasNext()) {
                Student stu = (Student)it.next();
                sop(stu.getName()+"...."+stu.getAge());
            }
            
        }
    
    }
    class Student implements Comparable {//该接口强制让学生具备比较性
        private String name;
        private int age;
        
        Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
        
        public int compareTo(Object obj) {
            
            //return 0;
            
            if(!(obj instanceof Student))
                throw new RuntimeException("不是学生对象");
            Student s = (Student)obj;
            
            System.out.println(this.name+"....compareTo...."+s.name);
            if(this.age > s.age)
                return 1;
            if(this.age == s.age)
                return this.name.compareTo(s.name);
            return -1;
            
        }
        
        public String getName() {
            return name;
        }
        
        public int getAge() {
            return age;
        }
    }

       记住,排序时,当主要条件相同时,一定判断一下次要条件。

       当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让容器自身具备比较性。定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。定义一个类实现Comparator接口,覆盖compare()方法。

       当两种排序都存在时,以比较器为主。

       int compare(T o1, T o2):比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。

       示例代码如下:

    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.TreeSet;
    
    public class TreeSetDemo1 {
        public static void sop(Object obj) {
            System.out.println(obj);
        }
    
        public static void main(String[] args) {
            TreeSet ts = new TreeSet(new MyCompare());
            
            ts.add(new Student1("lisi02", 22));
            ts.add(new Student1("lisi007", 20));
            ts.add(new Student1("lisi09", 19));
            ts.add(new Student1("lisi06", 18));
            ts.add(new Student1("lisi007", 29));
            ts.add(new Student1("lisi06", 18));
            //ts.add(new Student("lisi02", 22));
            
            Iterator it = ts.iterator();
            
            while(it.hasNext()) {
                Student1 stu = (Student1)it.next();
                sop(stu.getName()+"...."+stu.getAge());
            }
        }
    
    }
    class MyCompare implements Comparator {
    
        @Override
        public int compare(Object o1, Object o2) {
            Student1 s1 = (Student1)o1;
            Student1 s2 = (Student1)o2;
            
            int num = s1.getName().compareTo(s2.getName());
            if(num == 0) {
                /*
                if(s1.getAge() > s2.getAge()) {
                    return 1;
                }
                if(s1.getAge() == s2.getAge()) {
                    return 0;
                }
                return -1;
                */
                return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
            }
            return num;
            
        }
        
    }
    class Student1 implements Comparable {//该接口强制让学生具备比较性
        private String name;
        private int age;
        
        Student1(String name, int age) {
            this.name = name;
            this.age = age;
        }
        
        public int compareTo(Object obj) {
            
            //return 0;
            
            if(!(obj instanceof Student1))
                throw new RuntimeException("不是学生对象");
            Student1 s = (Student1)obj;
            
            System.out.println(this.name+"....compareTo...."+s.name);
            if(this.age > s.age)
                return 1;
            if(this.age == s.age)
                return this.name.compareTo(s.name);
            return -1;
            
        }
        
        public String getName() {
            return name;
        }
        
        public int getAge() {
            return age;
        }
    }

       练习:按照字符串长度排序。

       分析:字符串本身具备比较性,但是它的比较方式不是所需要的,这时就只能使用比较器。

       示例代码如下:

    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.TreeSet;
    
    class StringLengthComparator implements Comparator {
    
        @Override
        public int compare(Object o1, Object o2) {
            String s1 = (String) o1;
            String s2 = (String) o2;
            /*
            if(s1.length() > s2.length()) {
                return 1;
            }
            if(s1.length() == s2.length()) {
                return 0;
            }
            */
            int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
            if(num == 0) {
                return s1.compareTo(s2); //如果两个字符串的长度相同,再按他俩的字典顺序排序。
            }
            return num;
        }
        
    }
    public class TreeSetTest {
    
        public static void main(String[] args) {
            TreeSet ts = new TreeSet(new StringLengthComparator());
            
            ts.add("abcd");
            ts.add("cc");
            ts.add("cba");
            ts.add("aaa");
            ts.add("z");
            ts.add("hahaha");
            
            Iterator it = ts.iterator();
            
            while(it.hasNext()) {
                System.out.println(it.next());
            }
        }
    
    }

       泛型

       泛型:JDK1.5版本以后出现的新特性。用于解决安全问题,是一个类型安全机制。

       泛型的好处:

    1. 将运行时期出现的问题ClassCastException,转移到了编译时期,方便于程序员解决问题,让运行时期问题减少,安全。
    2. 避免了强制转换的麻烦。

       泛型格式:通过<>来定义要操作的引用数据类型。

       问:在使用java提供的对象时,什么时候写泛型呢?

       答:通常在集合框架中很常见,只要见到<>就要定义泛型。其实<>就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。

       示例代码如下:

    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class GenericDemo {
    
        public static void main(String[] args) {
            
            ArrayList<String> al = new ArrayList<String>();
            
            al.add("abc01");
            al.add("abc0991");
            al.add("abc014");
            
            //al.add(4);//al.add(new Integer(4));
            
            Iterator<String> it = al.iterator();
            while(it.hasNext()) {
                String s = it.next();
                System.out.println(s + ":" + s.length());
            }
        }
    
    }

       练习:按照字符串长度排序。

       代码:

    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.TreeSet;
    
    class LenComparator implements Comparator<String> {
    
        @Override
        public int compare(String arg0, String arg1) {
            int num = new Integer(arg0.length()).compareTo(new Integer(arg1.length()));
            
            if(num == 0)
                return arg0.compareTo(arg1);//如果两个字符串的长度相同,再按他俩的字典顺序排序。
            
            return num;
        }
    
    }
    public class GenericDemo1 {
    
        public static void main(String[] args) {
            TreeSet<String> ts = new TreeSet<String>(new LenComparator());
            
            ts.add("abcd");
            ts.add("cc");
            ts.add("cba");
            ts.add("aaa");
            ts.add("z");
            ts.add("hahaha");
            
            Iterator<String> it = ts.iterator();
            
            while(it.hasNext()) {
                String s = it.next();
                System.out.println(s);
            }
        }
    
    }

       什么时候定义泛型类

       当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展。现在定义泛型来完成扩展。

       如:

    class Worker {
        
    }
    
    class Stud {
        
    }
    //泛型前做法
    class Tool {
        private Object object;
        
        public void setObject(Object object) {
            this.object = object;
        }
        
        public Object getObject() {
            return object;
        }
    }
    //什么时候定义泛型类?
    //当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展。
    //现在定义泛型来完成扩展。
    class Utils<QQ> {
        private QQ q;
        
        public void setObject(QQ q) {
            this.q = q;
        }
        
        public QQ getObject() {
            return q;
        }
        
    }
    public class GenericDemo2 {
    
        public static void main(String[] args) {
            Utils<Worker> u = new Utils<Worker>();
            u.setObject(new Worker());
            Worker w = u.getObject();
            
            /*
            Tool t = new Tool();
            t.setObject(new Stud());
            Worker w = (Worker)t.getObject();
            */
        }
    
    }

       

       泛型方法

       泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。

       特殊之处:静态方法不可以访问类上定义的泛型。

       如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。

       示例代码:

    /*
    class DemoG<T> {
        public void show(T t) {
            System.out.println("show:" + t);
        }
        
        public void print(T t) {
            System.out.println("print:" + t);
        }
        
    }
    */
    //泛型类定义的泛型,在整个类中有效。如果被方法使用,
    //那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。
    //为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。
    
    /*
    特殊之处:静态方法不可以访问类上定义的泛型。
    如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。
    */
    
    class DemoG<T> {
        public void show(T t) {
            System.out.println("show:" + t);
        }
        //泛型方法
        public <Q> void print(Q q) {
            System.out.println("print:" + q);
        }
        //静态泛型方法
        public static <W> void method(W t) {
            System.out.println("method:" + t);
        }
    }
    public class GenericDemo3 {
    
        public static void main(String[] args) {
            DemoG<String> d1 = new DemoG<String>();
            d1.show("haha");
            //d1.show(4);
            d1.print(4);
            d1.print("hello");
            DemoG.method("hahahha");
            
            /*
            DemoG d = new DemoG();
            d.show("haha");
            d.show(new Integer(4));
            
            d.print("heihei");
            */
            /*
            DemoG<Integer> d = new DemoG<Integer>();
            d.show(new Integer(4));
            d.print("haha");
            
            DemoG<String> d1 = new DemoG<String>();
            d1.print("haha");
            d1.show(5);
            */
        }
    }

       泛型接口

       示例代码:

    //泛型定义在接口上
    interface Inter<T> {
        void show(T t);
    }
    /*
    泛型接口的第一种实现方式:
    class InterImpl implements Inter<String> {
        public void show(String t) {
            System.out.println("show:" + t);
        }
    }
    */
    
    /*
    泛型接口的第二种实现方式:
    */
    class InterImpl<T> implements Inter<T> {
    
        @Override
        public void show(T t) {
            System.out.println("show:" + t);
        }
        
    }
    public class GenericDemo4 {
    
        public static void main(String[] args) {
            InterImpl<Integer> i = new InterImpl<Integer>();
            i.show(4);
            
            
            //InterImpl i = new InterImpl();
            //i.show("haha");
        }
    
    }

       

       泛型的限定

       ?:通配符,也可以理解为占位符。

       泛型的限定:

    1. ? extends E:可以接收E类型或者E类型的子类型,上限。
    2. ? super E:可以接收E类型或者E的父类型,下限。

       示例代码如下:

    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.Iterator;
    
    class PersonG {
        private String name;
    
        
        public PersonG(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        
    }
    
    class StudentG extends PersonG {
        public StudentG(String name) {
            super(name);
        }
    }
    
    public class GenericDemo5 {
    
        public static void main(String[] args) {
            /*
            ArrayList<String> al = new ArrayList<String>();
            
            al.add("abc1");
            al.add("abc2");
            al.add("abc3");
            
            ArrayList<Integer> al1 = new ArrayList<Integer>();
            
            al1.add(4);
            al1.add(7);
            al1.add(1);
            
            printColl(al);
            printColl(al1);
            */
            ArrayList<PersonG> al = new ArrayList<PersonG>();
            
            al.add(new PersonG("abc1"));
            al.add(new PersonG("abc2"));
            al.add(new PersonG("abc3"));
            //printColl(al);
            
            ArrayList<StudentG> al1 = new ArrayList<StudentG>();
            
            al1.add(new StudentG("abc---1"));
            al1.add(new StudentG("abc---2"));
            al1.add(new StudentG("abc---3"));
            
            printColl(al1);// ArrayList<PersonG> al = new ArrayList<StudentG>();error----泛型中无法向上转型
         }
        
        public static void printColl(ArrayList<? extends PersonG> al) {//ArrayList<String> al = new ArrayList<Integer>(); error
            Iterator<? extends PersonG> it = al.iterator();
            
            while(it.hasNext()) {
                System.out.println(it.next().getName());
            }
        }
        
        /*
        public static <T> void printColl_1(ArrayList<T> al) {//ArrayList<String> al = new ArrayList<Integer>(); error
            Iterator<T> it = al.iterator();
            
            while(it.hasNext()) {
                T t = it.next();//可以接收T类型并操作
                System.out.println(t);
            }
        }
        
        public static void printColl(ArrayList<?> al) {//ArrayList<String> al = new ArrayList<Integer>(); error
            Iterator<?> it = al.iterator();
            
            while(it.hasNext()) {
                System.out.println(it.next());
                //System.out.println(it.next().length());//不能使用类型特有方法:length()
            }
        }
        */
    }

       现在重点讲解泛型的下限。通过如下代码示例说之:

       泛型的下限的应用举例:

    TreeSet(Comparator<? super E> comparator) 
    //伪代码:
    class
    PersonG { private String name; public PersonG(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class StudentG extends PersonG { public StudentG(String name) { super(name); } } class StudentG implements Comparable<PersonG> {//<? super E> @Override public int compareTo(PersonG arg0) { return 0; } } class Comp implements Comparator<PersonG> {//可以接收StudentG,也可以接收StudentG的父类型PersonG @Override public int compare(PersonG arg0, PersonG arg1) { PersonG arg0 = new StudentG("abc---1"); return arg0.getName().compareTo(arg1.getName()); } } TreeSet<StudentG> ts = new TreeSet<StudentG>(new Comp()); ts.add(new StudentG("abc---1")); ts.add(new StudentG("abc---2")); ts.add(new StudentG("abc---3"));

       现示例说明:

    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.TreeSet;
    
    class PersonGe {
        private String name;
    
        
        public PersonGe(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        
    }
    
    class StudentGe extends PersonGe {
        public StudentGe(String name) {
            super(name);
        }
    }
    
    class WorkerGe extends PersonGe {
        public WorkerGe(String name) {
            super(name);
        }
    }
    /*
    class StuComp implements Comparator<StudentGe> {
    
        @Override
        public int compare(StudentGe s1, StudentGe s2) {
            
            return s1.getName().compareTo(s2.getName());
        }
        
    }
    class WorkerComp implements Comparator<WorkerGe> {
    
        @Override
        public int compare(WorkerGe s1, WorkerGe s2) {
            
            return s1.getName().compareTo(s2.getName());
        }
        
    }
    */
    class Comp implements Comparator<PersonGe> {
    
        @Override
        public int compare(PersonGe p1, PersonGe p2) {
            return p2.getName().compareTo(p1.getName());//局限性:只能用父类型的方法
        }
        
    }
    public class GenericDemo6 {
    
        public static void main(String[] args) {
            
            TreeSet<StudentGe> ts = new TreeSet<StudentGe>(new Comp());
            ts.add(new StudentGe("abc03"));
            ts.add(new StudentGe("abc02"));
            ts.add(new StudentGe("abc06"));
            ts.add(new StudentGe("abc01"));
            
            Iterator<StudentGe> it = ts.iterator();
            
            while(it.hasNext()) {
                System.out.println(it.next().getName());
            }
            
            
            TreeSet<WorkerGe> ts1 = new TreeSet<WorkerGe>(new Comp());
            ts1.add(new WorkerGe("wabc--03"));
            ts1.add(new WorkerGe("wabc--02"));
            ts1.add(new WorkerGe("wabc--06"));
            ts1.add(new WorkerGe("wabc--01"));
            Iterator<WorkerGe> it1 = ts1.iterator();
            
            while(it1.hasNext()) {
                System.out.println(it1.next().getName());
            }
            
        }
    
    }

      

  • 相关阅读:
    1602液晶显示实验
    LNMP安装(二)
    LNMP安装(一)
    vim插件安装
    资料下载
    建表的sql
    time
    计算机里的加减乘除
    branch
    存储过程
  • 原文地址:https://www.cnblogs.com/yerenyuan/p/5257022.html
Copyright © 2020-2023  润新知