毕向东之集合Collection与泛型

/*
 为什么出现集合类:
     面向对象语言对事物的体现都是对对象的形式,所以为了方便对多个对象的操作,
     就对象进行存储,集合就是存储对象最常用的一种方式。
数组和集合类同是容器,有何不同?
    数组虽然也可以存储对象,但长度是固定的,集合长度是可变的。
    数组中可以存储基本数据类型,集合只能存储对象。
集合类的特点:
    集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
2.集合中存储的都是对象的引用(地址)。

迭代器:就是集合的取出元素的方式。
 */
import java.util.ArrayList;
import java.util.Iterator;
public class Test1 {
    public static void main(String[] args) {
        method_3(); 
    }
    public static void method_3(){
        ArrayList al=new ArrayList();
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add("java04");
        Iterator it=al.iterator();//获取迭代器,用于取出集合中的元素
        while(it.hasNext()){//判断有没有内容
            sop(it.next());
        }
    }
    public static void method_2(){
        ArrayList al1=new ArrayList();
        al1.add("java01");
        al1.add("java02");
        al1.add("java03");
        al1.add("java04");
        ArrayList al2=new ArrayList();
        
        al2.add("java01");
        al2.add("java02");
        al2.add("java05");
        al2.add("java06");
        al1.retainAll(al2);//取交集,al1中只会保留和al2中相同的元素
        sop("al1:"+al1);//al1:[java01, java02]
        sop("al2:"+al2);//al2:[java01, java02, java05, java06]
    }
    public static void method_1(){
        //创建一个集合容器。使用Collection接口的子类ArrayList
        ArrayList al=new ArrayList();
        //1.添加元素
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add("java04");
        //打印集合
        sop(al);//[java01, java02, java03, java04]
        //2.获取个数,集合长度
        sop("size:"+al.size());//size:4
        //3.删除元素
        al.remove("java02");//[java01, java03, java04]
        al.clear();//清空集合
        //4.判断元素
        sop("java03是否存在:"+al.contains("java03"));
        sop("集合是否为空:"+al.isEmpty());
        sop(al);        
    }
    public static void sop(Object obj){
        System.out.println(obj.toString());
    }
}

 

 

/*
Collection(有的方法:add remove contains包含   clear清空    iterator)
     |--List:元素是有序的,元素可以重复,因为该集合体系有索引
     注意:ArrayList和LinkedList中contains和remove判断的依据都是调用equals,所以需要重写
         |--ArrayList:底层的数据结构使用的是数组结构。特点:查找速度快,增删慢。   线程不同步
         |--LinkedList:底层的数据结构使用的是链表结构。特点:查找慢,增删快
         |--Vector:底层是数组数据结构。  线程同步。    被ArrayList替代了
     |--Set:元素是无序(存入和取出的顺序不一定一致)的,元素不可以重复。
         |--HashSet:底层数据结构是哈希表(对于重复判断的依据是:哈希值与内容都相同时才表示重复)
                     如果元素的HashCode值相同才会去判断equals是否为true.
                     所以尽量保证hashCode值的唯一性,减少调用equals带来的效率
                     所以有时需要重写hashCode方法和equals方法
         |--TreeSet:可以对Set集合中的元素进行排序(底层数据结构是二叉树:返回0,负数,正数)
                     TreeSet排序的第一种方式:让元素自身具备比较性,元素需要
                                 实现Comparable接口,覆盖compareTo方法
                     TreeSet排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的。
                         这时就需要让集合自身具备比较性。即让集合初始化时,就有了比较方式。
                         定义一个类,实现Comparator接口,覆盖compare方法。
                         当两种排序方式都存在时,以比较器为主。
List:(特有方法)
    特有方法:凡是可以操作角标的方法都是该体系特有的方法。
增    add(index,element);//角标,元素
    addAll(index,Collection);//添加集合 一堆元素
删        remove(index);
改    set(index,element);
查    get(index);
    subList(from,to);//从哪到哪 子串
    listIterator();
List集合特有的迭代器:ListIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发送异常(不能并行两种方式同时操作集合)
所以,在迭代器时,只能使用迭代器的方法操作元素,可是Iterator方法是有限的,
只能对元素进行判断、取出、删除的操作
如果想要其他的操作(添加、修改等)就需要使用其子接口:ListIterator
该接口只能通过List集合的listIterator方法获取。

LinkedList:特有方法
    addFirst();
    addLast();
    getFirst();
    getLast();//获取元素,但不删除元素,如果集合中没有元素会出现NoSuchElementException
    removeFirst();
    removeLast();//获取元素,但是元素被删除,如果集合中没有元素会出现NoSuchElementException
    
    在jdk1.6出现了替代方法
    offerFirst();
    offerLast();//头部添加元素
    
    peekFirst();
    peekFirst();//获取元素,但是不删除元素,如果集合中没有元素会返回null
    
    pollFirst();
    pollLast();//获取元素,但是元素被删除,如果集合中没有元素会返回null
 */
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public class Test2 {
    public static void main(String[] args) {
        ArrayList al=new ArrayList();
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add("java04");
        sop(al);
        ListIterator li=al.listIterator();
        while(li.hasNext()){
            Object ob=li.next();
            if(ob.equals("java02")){
                li.add("jia");
            }            
        }
        sop(al);
        
    }
    public static void sop(Object obj){
        System.out.println(obj);
    }
}

 

 

/*去除ArrayList集合中的重复元素
注意:ArrayList和LinkedList中contains和remove判断的依据都是调用equals,所以需要重写
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public class Test3 {
    public static void main(String[] args) {
        ArrayList al=new ArrayList();
        al.add(new Person("张山",3));//相当于Object obj=new Person("张山",3);
        al.add(new Person("李四",4));//所以下面必须向下转型
        al.add(new Person("王五",5));
        al.add(new Person("王五",5));
        al.add(new Person("张山",3));
        al=singleElement(al);
        ListIterator it=al.listIterator();
        while(it.hasNext()){
            Person p=(Person)it.next();
            sop(p.getName()+"..."+p.getAge());
        }
    }
    public static ArrayList singleElement(ArrayList al){
        ArrayList newAl=new ArrayList();
        Iterator it=al.iterator();
        while(it.hasNext()){
            Object obj=it.next();
            if(!newAl.contains(obj)){//contains底层调用equals来判断是不是相等
                newAl.add(obj);
            }
        }
        return newAl;
    }
    public static void sop(Object obj){
        System.out.println(obj);
    }
}
class Person{
    private String name;
    private int age;
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }
    public boolean equals(Object obj){//***参数列表不一致不叫复写
        if(obj instanceof Person){
            Person p=(Person) obj;
            if(this.getName()==p.getName() && this.getAge()==p.getAge()){
                return true;
            }
        }
        return false;
    }
}

 

 

/*需求:(元素具备比较性:都有年龄)
 往TreeSet集合中存储自定义对象学生。
 想按照学生的年龄进行排序
 
注意:排序时,当主要调节相同时,判断次要条件
只要控制compareTo方法返回的值就能控制元素的排序

因为String类中存在compareTo方法,按照字典的序列排序返回1 0 -1(表示大 相同  小)
所以当元素是字符串时,默认按照字典顺序排列
 */
import java.util.Iterator;
import java.util.TreeSet;
public class Test4 {
    public static void main(String[] args) {
        TreeSet ts=new TreeSet();//默认Comparable,根据元素的自然顺序进行排序
        ts.add(new Students("zhang",10));
        ts.add(new Students("wang",11));//自动调用底层compareTo方法进行比较
        ts.add(new Students("tang",11));
        ts.add(new Students("huang",20));
        Iterator it=ts.iterator();
        while(it.hasNext()){
            Students s=(Students)it.next();
            sop(s.getName()+"..."+s.getAge());
        }
    }
    public static void sop(Object obj){
        System.out.println(obj);
    }
}
class Students implements Comparable{//该接口让Students类具备比较性
    private String name;
    private int age;
    public Students(String name,int age){
        this.name=name;
        this.age=age;
    }
    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }
    public int compareTo(Object obj){
        if(!(obj instanceof Students))
            throw new RuntimeException("不是学生对象");
        Students s=(Students)obj;
        if(this.age>s.age){//表明按照年龄的大小排序
            return 1;//代表当前存的元素比前面已存的元素大,就存在已有元素的后面
        }else if(this.age==s.age){//当年龄相同时,再判断姓名是否相同
            return this.name.compareTo(s.name);//字符串.方法();
        }//String类中的compareTo方法按照字典的序列排序返回1 0 -1(表示大 相同  小)
        return -1;
    }
    
}

 

 

/*
 元素自身不具备比较性,或者具备的比较性不是所需要的,这时需要让容器自身具备比较器。
 定义比较器,将比较器对象作为参数传递给TerrSet集合的构造函数。
 */
import java.util.*;

public class Test5 {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new MyCompare());//使用自己的排序方式
        ts.add(new Students("zhang", 10));
        ts.add(new Students("wang", 11));// 自动调用底层compareTo方法进行比较
        ts.add(new Students("tang", 11));
        ts.add(new Students("tang", 11));
        ts.add(new Students("huang", 20));
        Iterator it = ts.iterator();
        while (it.hasNext()) {
            Students s = (Students) it.next();
            sop(s.getName() + "..." + s.getAge());
        }
    }
    public static void sop(Object obj) {
        System.out.println(obj);
    }
}
class MyCompare implements Comparator {
    public int compare(Object o1, Object o2) {
        Students s1 = (Students) o1;
        Students s2 = (Students) o2;
        int num = s1.getName().compareTo(s2.getName());
        if (num == 0) {// 姓名相同判断年龄
            return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
        }
        return num;
    }
}

 

 

import java.util.*;
public class Test6 {
    public static void main(String[] args) {
        TreeSet ts=new TreeSet(new StrLenCompare());
        ts.add("abs");
        ts.add("abaa");
        ts.add("absbf");
        ts.add("aba");
        Iterator it=ts.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}
class StrLenCompare implements Comparator{
    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 s1.compareTo(s2);
//        return -1;
//=============第二种写法================================= 
        int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));
        if(num==0)
            return s1.compareTo(s2);
        return num;
    }
}

 

 

/*泛型:jdk1.5版本以后出现的新特性,解决安全问题。<类>尖括号用来接收数据类型
 因为集合添加的元素是Object类可以添加任何类型,但在用元素的方法时需要对元素进行向下转型
好处:1.将运行时期类型转换异常异常(ClassCastException),转移到了编译时期,
    方便于程序员对问题的解决
    2.避免了强制转换的麻烦
在比较器中写泛型,compare方法就不需要强制
 */
import java.util.*;
public class Test7 {
    public static void main(String[] args) {
        ArrayList<String> al=new ArrayList<String>();//String类型的容器
        al.add("abc");
        al.add("abcd");
        al.add("ab");
        //al.add(4);//运行时出错
        Iterator<String> it=al.iterator();//String类型的迭代器给String的it,
        while(it.hasNext()){            //就不需要强制转换了
            String s=it.next();//因为需要转为特定的类型,所以添加的元素必须一致
            System.out.println(s.length());//才能使用长度的方法
        }
    }
}

 

 

/*泛型类:什么时候定义泛型类?注意:只能是引用数据类型(自定义类、Integer),不能是基本数据类型(int、char)
当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在定义泛型类来完成扩展.
 */
public class Test8 {
    public static void main(String[] args) {
        Tool<Work> work=new Tool<Work>();//替代QQ类型
        work.setQQ(new Work());
        System.out.println(work.getQQ());
        
        Tool1 t=new Tool1();
        t.show("哈哈");
        t.print(5);
        t.show(new Integer(5));
        t.show(4);
    }
}
/*但是泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象
明确要操作的具体类型后,所有要操作的类型就已经固定了
为了让不同方法可以操作不同的类型,而且类型还不确定,那么就可以将泛型定义在方法上
特殊之处:静态方法不能访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,
可以将泛型定义在方法上。
*/
class Tool<QQ>{//QQ类型:泛型定义在类上
    private QQ q;
    public void setQQ(QQ q){//局限性:随着类中QQ的确定而确定
        this.q=q;
    }
    public QQ getQQ(){
        return q;
    }
    public static <M> void method(M m){
        System.out.println(m);
    }//因为静态比对象先加载,而类上的泛型需要在创建对象的时候才能确定,所以不能将M改为QQ
}
class Tool1{//泛型定义在方法上
    public <T> void show(T t){//作用域只在该函数上
        System.out.println(t);
    }
    public <T> void print(T t){//所以与上函数T没关系
        System.out.println(t);
    }//只有定义了泛型,才能用泛型的名称,所以方法上的<T>不能不写
}
class Work{}
class Student{}

 

 

/*泛型既可以定义在方法上、类上、接口上、也可以同时定义在类上和方法上等等,
泛型只是解决了代码的复用性,使一个方法可以接收多种类型
泛型的高级应用(限定):
? 通配符,也可以理解为占位符(表示可以接收任意类型)。
? extends E :可以接收E类型或者E的子类型。上限(限制了父类)。
?super E :可以接收E类型或者E的父类型。下限(限制了子类)。
泛型中的继承关系
            a、三种情况:
                (1)子类继承时,父类指定具体类型 子类可泛型也可以不泛型
                格式:class 子类名<泛型字母表>extends 父类名<引用数据类型> 
                (2)子类继承时,父类类型还是泛型
                格式:class 子类名<泛型字母表a>extends 父类名<泛型字母表b> a包含b
                (3)类继承时,父类类型不指定类型
                格式:class 子类名<泛型字母表>extends 父类名 子类可以泛型也可以不泛型
                称之为泛型擦除,统一用Object代替
            b、注意:
                (1)子类泛型>=父类泛型,也就是要比父类更宽的泛型
                (2)属性:
                父类属性类型随父类
                子类属性类型随子类
                (3)重写方法:
                类型随父类
 */
import java.util.*;
public class Test9 {
    public static void main(String[] args){
        ArrayList<Dog> al=new ArrayList<Dog>();
        al.add(new Dog("dog1"));
        al.add(new Dog("dog2"));
        al.add(new Dog("dog3"));
        ArrayList<Animal> all=new ArrayList<Animal>();
        all.add(new Animal("animal1"));
        all.add(new Animal("animal2"));
        all.add(new Animal("animal3"));
        print(al);
        print(all);
    }
    public static void print(ArrayList<? extends Animal> t){
        Iterator<? extends Animal> it=t.iterator();
        while(it.hasNext()){
            System.out.println(it.next().getName());
        }
    }
}
class Dog extends Animal{
    public Dog(String name){
        super(name);
    }
}
class Animal{
    private String name;
    public Animal(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
}

 

 

import java.util.*;
public class Test10 {
    public static void main(String[] args) {
        TreeSet<Studen> ts1=new TreeSet<Studen>(new ComPer());
        ts1.add(new Studen("s1"));
        ts1.add(new Studen("s2"));
        ts1.add(new Studen("s3"));
        method(ts1);
        TreeSet<Worker> ts2=new TreeSet<Worker>(new ComPer());
        ts2.add(new Worker("w1"));
        ts2.add(new Worker("w2"));
        ts2.add(new Worker("w3"));
        method(ts2);
    }
    public static void method(TreeSet<? extends Person1> t){//增加输出的复用性
        Iterator<? extends Person1> it=t.iterator();
        while(it.hasNext()){
            System.out.println(it.next().getName());
        }
    }
}
class ComPer implements Comparator<Person1>{//利用多态,子类都可以用这比较器
    public int compare(Person1 p1,Person1 p2){//局限:但是只能用父类的方法
        return p1.getName().compareTo(p2.getName());
    }
}
class Studen extends Person1{
    public Studen(String name){
        super(name);
    }
}
class Worker extends Person1{
    public Worker(String name){
        super(name);
    }
}
class Person1{
    private String name;
    public Person1(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
}

补充:

1.list集合的排序:

Collections.sort(list,new MyTimeSort()); //对list集合的排序
/**
 * 对时间的格式化和升序排序  想根据什么排就什么排,由compare的返回值决定
 */
class MyTimeSort implements Comparator{

      @Override
     public int compare(Object lhs, Object rhs) {
           String s1 = (String) lhs;
           String s2 = (String) rhs;
           long int1 = formatTime(s1);
           long int2 = formatTime(s2);
           return new Long(int1).compareTo(new Long(int2));
     }
}

 

posted @ 2016-05-31 12:51  ts-android  阅读(243)  评论(0编辑  收藏  举报