黑马程序员---集合框架(Collection)和泛型

来源:互联网 发布:翻墙软件 自由 编辑:程序博客网 时间:2024/05/22 10:06

------- Java、.Net、Android培训期待与您交流!------- 

一、Collection:

<>集合(集合框架)Collection
        用于存放对象,可以存放不同类型的对象,长度是可变的。而数组也可以存放对象,但是需要存放同类型的对象且长度是固定的。
Collection定义了集合框架的共性功能。
1、添加:
        add(Object obj);
        addAll(collection);
2、删除:返回类型是boolean
        removed(e);
        removeAll(collection);
3、判断:返回类型是boolean
        contains(e);
        isEmpty( );
4、获取:
        iterator( );
        size( );
5、获取交集:返回类型是boolean
        retainAll( );
6、集合变数组:
        toArray( );

注意:1add方法的参数类型是Object,以便于接收任意类型对象。
            2、集合中存储的都是对象的引用(地址)

迭代器:
        其实就是集合的取出元素的方式。迭代器是取出方式,会直接访问集合中的元素。所以将迭代器通过内部类的形式来进行描述,通过容器的iterator( )方法获取该内部类的对象。

<>ListSet集合:

|--Collection
        |--List:元素是有序的,元素可以重复。因为该集合体系有索引。
                |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快,但是增删稍慢,线程不同步。
                |--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢,线程不同步。
                |--Vector:底层是数组数据结构。线程同步,被ArrayList替代了,因为效率低。
        |--Set:元素是无序(存入取出的顺序不一致),元素不可以重复。

                |--HashSet:数据结构是哈希表,线程是非同步的。
                        保证元素唯一性的原理:判断元素的hashCode值是否相同。
                        如果相同,还会继续判断元素的equals方法,是否为true

                |--TreeSet:可以对Set集合中的元素进行排序。底层数据结构是二叉树。
                        保证元素唯一性的依据:compareTo方法:return 0

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

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

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

List:特有方法。凡是可以操作角标的方法都是该体系特有的方法。
        增:
                add(index,element);
                addAll(index,Collection);
        删:
                remove(index);
        改:
               set(index,element);
        查:
                get(index):
                subList(from,to);
                listIterator();   //列表迭代器
                int indexOf(obj):获取指定元素的位置。
                ListIterator listIterator();

        List集合特有的迭代器:ListIteratorIterator的子接口。在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生并发异常ConcurrentModificationException。所以,在迭代器时,只能用迭代器的方法过操作元素。可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作。如果想要其他的操作如添加,修改等,就需要使用其子接口:ListIterator。该接口只能通过List集合的listIterator方法获取,为了避免发生并发异常,需要对列表迭代器进行加锁。

示例1ArrayList中可以存放重复元素,该怎么去除重复元素呢?

        需求:去除ArrayList集合中的重复元素。
        思路:
                1.对去除重复元素的方法进行封装成类;
                2.提取去重复元素方法,单独封装;
                3.提供一个对外方法来获取去重后的集合;
                4.调用该方法来实现去除ArrayList集合的重复元素。
        步骤:
                1.创建RemoveRepetition类,封装去重复元素的方法;
                2.声明两个成员集合变量;
                3.通过带参数列表(ArrayList al)构造函数来实现两个成员变量;
                4.定义removeRepetitionDate来实现去重方法,通过使用迭代器来实现循环,并在新集合中判断每次next()的元素是否存在,不存在的话就将该元素添加到新集合;
                5.提供对外方法myGet来获取去重后的新集合。
                6.在main方法中创建带重复元素的集合,并将该集合作为值传递到 new RemoveRepetition(al)对象中。

import java.util.*;class  RemoveRepetitionTest{public static void main(String[] args) {//创建数组集合ArrayList al = new ArrayList();//添加元素al.add("Array01");al.add("Array02");al.add("Array01");al.add("Array02");al.add("Array01");al.add("Array03");//创建对象,将集合al作为值传递RemoveRepetition r = new RemoveRepetition(al);//获取去除重复后的数组集合ArrayList newAl = r.myGet();sop(newAl);//<=>sop(r.myGet());}private static void sop(Object obj){System.out.println(obj);}}//对去除重复元素类进行封装class RemoveRepetition{private ArrayList al;private ArrayList newAl;RemoveRepetition(ArrayList al){this.al = al;newAl = new ArrayList();}//去除重复元素方法private void removeRepetitionDate(){for (Iterator it = al.iterator(); it.hasNext(); ){Object obj = it.next();//将获取元素赋给超类引用if (!newAl.contains(obj))//判断新集合中是否存在该元素newAl.add(obj);    //不存在的话,将该元素添加到新集合中}}//获取去重后的新集合public ArrayList myGet(){removeRepetitionDate();return newAl;}}

示例2:前面在介绍字符串时有这么一题,下面我们用TreeSetTest来做。

        需求:"90 -7 0 18 2 45 4" ,将字符串中的数值进行排序。使用TreeSet完成。

        思路
                1,将字符串切割。
                2,将子串转成整数对象,然后将这些对象存入TreeSet集合。因为TreeSet自身具备排序功能。

class  TreeSetTest2{public static void main(String[] args) {String str = "90 -7 0 18 2 45 4";System.out.println(str);String[] arr = str.split(" ");//切割字符串,将获取的子串存入一个数组中//创建集合TreeSet ts = new TreeSet();//遍历数组,将获取的值添加到集合中for (int i=0; i<arr.length; i++){ts.add(Integer.parseInt(arr[i]));}System.out.println(ts);//创建字符串缓冲区(容器)StringBuilder sb = new StringBuilder();Iterator it = ts.iterator();//遍历集合for (int j=0; it.hasNext()&&j<arr.length; j++){if (j!=arr.length-1)sb.append(it.next()+" ");//想容器中添加经集合排序后的elsesb.append(it.next());}System.out.println(sb.toString());//将容器转成字符串打印}}

二、泛型

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

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

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

在使用java提供的对象时,什么时候写泛型呢?
        泛型在集合框架中很常见,只要见到< >就要定义泛型。其实< >就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到< >中即可。

        泛型声明在类上,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。

        为了让不同方法可以操作不同类型,而且类型还不确定。那么可以将泛型定义在方法上。

特殊之处:
        静态方法不可以访问类上定义的泛型。
        如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。

?    :通配符,也可以理解为占位符。
泛型的限定:
        ? extends E:可以接收E类型或者E的子类型。上限。
        ? super    E:可以接收E类型或者E的父类型。下限。

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

示例3:泛型的定义

class Utils<U>{private U u;public void setObject(U u){this.u = u;}public U getObject(){return u;}//将方法泛型,与类的泛型无关,独立存在public <T> void show(T t){System.out.println("show:"+t);}//注意泛型的格式,插入的位置,它修饰的是返回类型。且静态泛型只能方位静态成员,不能访问u变量。public static <E> void print(E e){System.out.println("print:"+e);}}class  GenericClass{public static void main(String[] args) {Utils<String> u = new Utils<String>();u.setObject("haaa");System.out.println(u.getObject());u.show("haha");u.show(4);u.print(5.6);Utils.print("yes");}}

        总结:集合,熟悉集合的基本操作,以及List集合(ArrayListLinkedList)Set集合(HashSetTreeSet)中各个子集合使用的原理是什么,这样有助于我们在选用集合时更有目的性。会使用迭代器,JDK1.5版本后迭代器将被高级for循环替代。泛型的使用。对于集合类中的泛型会用即可,可以看得懂上限下限,泛型类和泛型方法定义。

原创粉丝点击