黑马程序员—java基础学习--集合类、泛型

来源:互联网 发布:金融投资源码 编辑:程序博客网 时间:2024/04/30 15:49

当数据多的时候会出现数组,后来我们发现单纯的数组并不能解决所有的问题,后来变有了缓冲区,而缓冲区的出现也只能对文字进行操作,对于对象也有些略显不足,如今,更是出现了集合类,集合类的出现,使得我们开发的效率有进一步的提升,有了集合类,我们所写出的代码便更具观赏性。今天,一起走进集合类的世界。

*集合类

一、为什么出现集合类:

面向对象语言对实物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行储存,集合就是储存对象最常用的一种方式。

二、数组和集合类同时容器,有何不同:

数组虽然也可以储存对象,但长度是固定的,集合长度是可变的,数组中可以存储基本数据类型,集合只能存储对象。

三、集合类的特点:

1,集合只用于存储对象,

2,集合长度是可变的,

3,集合可以存储不同类型的对象,

4,集合中不可以存储基本数据类型值。

四、集合框架:


五、迭代器的使用:

1,什么是迭代器

其实就是集合的取出元素的方式。

2,迭代器的使用理解代码如下:

import java.util.*;class CollectionDemo{public static void main(String[] args) {ArrayList al = new ArrayList();//创建ArrayList容器al.add("java01");//向容器中添加对象al.add("java02");al.add("java03");al.add("java04");//使用Iterator接口对元素进行取出Iterator it = al.iterator();//获取迭代器,用于去除集合中的元素while(it.hasNext()){System.out.println(it.next());}}}
把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素,那么取出方式就被定义成了内部类,而每一个容器的数据结构不同,所以取出的动作细节也不一样,但是都有共性内容判断和取出,那么可以将共性抽取。

那么这些内部类都符合一个规则,该规则就是Iterator。如何获取集合的取出对象呢?就是通过一个对外提供的方法。iterator()

六、集合体系及特点:

Collection

    | - - List:元素是有序的,元素可以重复,因为该集合体系有索引。

        | - - ArrayList::底层的数据结构使用的是数组。特点:查询元素快,但是增删稍慢。线程不同步。

        | - - LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。

        | - - Vector:底层是数组数据结构,线程同步。被ArrayList替代。查询,增删都慢。(Vector集合只能使用枚举取出)

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


List:

特有方法,凡是可以操作角标的方法都是该体系特有的方法。

add(index,element);

addAll(index,Collection);

remove(index);

set(index,element);

get(index);

subList(from,to);

listIterator();

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

枚举:

枚举就是Vector特有的取出方式,发现枚举和迭代很像,其实枚举和迭代是一样的,因为枚举的名称以及方法名称都过长,所以枚举被迭代器取代了。

LinkedList:

特有方法

添加元素,无返回值:

addFirst ( )  ;

addLast ( ) ;

获取但不删除元素,如果集合中没有元素,会出现NoSuchElementException:

getFirst ( ) ;

getLast ( ) ; 

获取但删除元素,如果集合中没有元素,会出现NoSuchElementException:

removeFirst ( ) ;

removeLast ( ) ;

在JDK1.6出现了替代方法

添加元素,返回boolean类型返回值

offerFirst ( ) ;

offerLast ( ) ;

获取但不删除元素,如果集合中没有元素,会返回null

peekFirst ( ) ;

peekLast ( ) ;

获取但删除元素,如果集合中没有元素,会返回null

pollFirst ( ) ;

pollLast ( ) ;

面试题:使用LinkedList模拟一个堆栈或者队列数据结构

堆栈:先进后出

队列:先进先出

理解代码如下:

import java.util.*;class LinkedListTest {public static void main(String[] args) {DuiLie dl = new DuiLie();//创建DuiLie对象dl.myAdd("a1");//添加元素dl.myAdd("a2");dl.myAdd("a3");dl.myAdd("a4");while(!dl.isNull()){System.out.println(dl.myGet());}}class DuiLie{private LinkedList link;DuiLie(){//使得DuiLie对象一产生就创建了自己的容器link = new LinkedList();}public void myAdd(Object Obj){//将方法封装为自己的方法link.addFirst(obj);}public Object myGet(){link.removeLast();//将代码改成link.removeFirst(); 即为堆栈结构}public boolean isNull(){return link.isEmpty();}}

注意:List集合判断元素是否相同,依据的是元素的equals方法。


Set集合:

| - - Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复

    | - - HashSet:底层数据结构是哈希表,线程不同步;

    | - - TreeSet:底层数据结构是二叉树,线程不同步。

Set集合的功能和Collection的功能一致。

HashSet是如何保证元素的唯一性:

HashSet是通过元素的两个方法,hashCode和equals来完成,如果元素的hashCode值相同才会判断equals是否为true,如果元素的hashCode值不同,不会调用equal方法。

注意:对于判断元素是否存在以及删除等操作,依赖的方法是元素的hashCode()和equals()方法,先判断hashCode()方法。

TreeSet特点:

可以对Set集合中的元素进行排序,底层数据结构是二叉树,保证元素唯一性的一句是compareTo方法return 0。与hashCode和equals无关。

TreeSet排序的方式:

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

2,当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性,及定义一个类,实现Comparator接口,然后覆盖compara方法。在集合一初始化时,具有了比较方式。

当两种比较方式都存在时,以比较器为主。

*集合的安全机制——泛型

一、泛型概念:

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

二、泛型的好处:

1,将运行时期出现的问题ClassCastException,转移到了编译时期,方便于程序员解决问题,让运行时期的问题减少,安全。

2,避免了强制转换的麻烦。

三、泛型格式:

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

基本书写代码如下:

import java.util.*;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);//自动装箱 此时出异常,类型转换异常Iterator<String> it = al.iterator();while(it.hasNext()){String s = it.next();//此处有了泛型之后将不再做强制转换动作System.out.println(s.length());}}}
四、何时需要定义泛型类:
当类中要操作的引用数据类型不确定的时候,早起定义Object来完成扩展,现在定义泛型来完成扩展。

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

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

泛型在类,方法,接口中的应用:

import java.util.*;class Demo<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 w){//泛型放在返回值类型的前面System.out.println("method"+w);}}interface Inter<T>//定义泛型接口{void show(T t);}class InterImpl<T> implements Inter<T>//实现接口,但未明确定义泛型。{public void show(T t){System.out.println("show:"+t);}}class GenericDemo4 {public static void main(String[] args) {Demo<String> t = new Demo<String>();t.show("sds");//show方法随着泛型类走,所以只能传入类中的类型t.print(new Integer(4));//print方法泛型随着方法走,所以传入什么类型的都行。Demo.method("method");InterImpl<Integer> i = new InterImpl<Integer>();//在使用时才知道类型i.show(4);}}
五、泛型的高级应用

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

泛型的限定:

? extends E :可以接受E类型或者E的子类型,上限。

? super E:可以接受E类型或者E的父类型, 下限。


0 0
原创粉丝点击