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

    }

}

  

时间: 2024-10-05 06:27:26

Java集合框架(二)的相关文章

java 集合框架二(list)

/* Collection: |--List:集合中的元素是有序的,可重复的,有索引. |--Set:集合中的元素是无序的,不可重复的,无索引. List中的特有方法: 增 add(index,element); addAll(index,Collection); 删 remove(index); 改 set(index,element); 查 get(index); subList(start,end); listIterator(); 其他: indexOf(obj);//通过indexOf

(二)java集合框架综述

一集合框架图 说明:对于以上的框架图有如下几点说明 1.所有集合类都位于java.util包下.Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类.2. 集合接口:6个接口(短虚线表示),表示不同集合类型,是集合框架的基础.3. 抽象类:5个抽象类(长虚线表示),对集合接口的部分实现.可扩展为自定义集合类.4. 实现类:8个实现类(实线表示),对接口的具体实现.5. Collectio

jdk源码阅读笔记之java集合框架(二)(ArrayList)

关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手. ArrayList类定义: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco } span.s1 { color: #931a68 } public class ArrayList<E> extends AbstractList<E> implements List<E> ArrayList基本属性: /** *

我所理解Java集合框架的部分的使用(Collection和Map)

所谓集合,就是和数组类似--一组数据.java中提供了一些处理集合数据的类和接口,以供我们使用. 由于数组的长度固定,处理不定数量的数据比较麻烦,于是就有了集合. 以下是java集合框架(短虚线表示接口,长虚线表示抽象类,实线表示类,箭头表示实现接口或者继承)(在网络上找的图,不知道原作者,侵权请联系我删除)(总之,关系很复杂,所以不用记得这个图,只是用来吓吓人而已的). 下面贴上个人理解之精简版之Collection(集)和Map(地图?暂且这么理解吧),话说思维导图蛮好用,以下是两幅思维导图

Java集合框架的知识总结

说明:面试准备,写的挺不错的. 转载地址: http://www.cnblogs.com/zhxxcq/archive/2012/03/11/2389611.html 1.综述 所有集合类都位于java.util包下.集合中只能保存对象(保存对象的引用变量).(数组既可以保存基本类型的数据也可以保存对象). 当我们把一个对象放入集合中后,系统会把所有集合元素都当成Object类的实例进行处理.从JDK1.5以后,这种状态得到了改进:可以使用泛型来限制集合里元素的类型,并让集合记住所有集合元素的类

Java集合框架(一)

Java集合框架结构图完整版 在完整版的结构图中Collection集合和Map下有许多未实现的抽象类(AbstractCollection.AbstractMap等等).下面整理一个简化版的,去除了一些不常用的子类和中间的一些抽象类. Java集合框架结构图简化版 说集合之前先来讲讲对象数组: 对象数组: 数组可以储存基本类型和引用类型,储存引用类型的数组叫对象数组(案例:用数组储存10个Animal类对象) 集合(Collection): a)集合的由来: Java语言是面对对象语言,需要操

Java集合框架实现自定义排序

Java集合框架针对不同的数据结构提供了多种排序的方法,虽然很多时候我们可以自己实现排序,比如数组等,但是灵活的使用JDK提供的排序方法,可以提高开发效率,而且通常JDK的实现要比自己造的轮子性能更优化. 一 .使用Arrays对数组进行排序 Java API对Arrays类的说明是:此类包含用来操作数组(比如排序和搜索)的各种方法. 1.使用Arrays排序:Arrays使用非常简单,直接调用sort()即可 int[] arr = new int[] {5,8,-2,0,10}; Array

java集合框架小结(进阶版)之HashMap篇

基本概念: Hash(哈希):hash一般也译作“散列”.事实上,就是一个函数,用于直接定址.将数据元素的关键字key作为变量,通过哈希函数,计算生成该元素的存储地址. 冲突:函数是可以多对一的.即:多个自变量可以映射到同一函数值.一般而言,不同的key的hash值是不同的.在往hash表中映射的时候,不同的hash值可能映射到同一存储地址,这种情况被称为冲突. 解决冲突的方法: 1. 链表法:将冲突的各个元素用一个一维数组来维护.(java源码实现) 2. 开发寻址法:具体的有线性探测法.二次

Java - 集合框架完全解析

来自:http://www.jianshu.com/p/63e76826e852 数据结构是以某种形式将数据组织在一起的集合,它不仅存储数据,还支持访问和处理数据的操作.Java提供了几个能有效地组织和操作数据的数据结构,这些数据结构通常称为Java集合框架.在平常的学习开发中,灵活熟练地使用这些集合框架,可以很明显地提高我们的开发效率,当然仅仅会用还是不够的,理解其中的设计思想与原理才能更好地提高我们的开发水平.下面是自己对Java集合框架方面的学习总结. 一.概述 二.Collection接