黑马程序员----集合类(一)

来源:互联网 发布:js 精确倒计时 编辑:程序博客网 时间:2024/05/16 18:24
------- android培训、java培训、期待与您交流! ----------

39、             集合类

1、 为什么出现集合类?

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

2、 数组和集合类同时容器,有何不同?

数组虽然也可以存储对象,但是长度固定;集合长度是可变的。

数组中可以存储基本数据类型,集合只能存储对象

3、 集合类的特点

集合只用于存储数据,集合长度是可变的,集合可以存储不同类型的对象

数据多了用对象、对象多了用集合【编程中都是这么操作的】

      4、集合框架的构成及分类

              图片一pic_1.jpg

 

      5、常用集合

              图片二pic_2.jpg

40、             Collection<E>

1、 Add(E e)方法的参数是Object(默认情况,即没有使用泛型的时候)。以便于接收任意类型的对象

2、 集合中存储的都是对象的引用(地址)

3Collection

1、             boolean removeAll(Collection<?> c)
移除此 collection 中那些也包含在指定 collection 中的所有元素。此调用返回后,collection 中将不包含任何与指定 collection 相同的元素。
2、             boolean retainAll(Collection<?> c)
仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。换句话说,移除此 collection 中未包含在指定 collection 中的所有元素。

4什么是迭代器,其实就是集合的取出元素的方式。

对于取出这个动作,不足以用一个方法来描述(一个方法搞不定),它需要多个功能来实现,当多个功能来实现的时候,就将多个功能封装到一个对象中去。对于不同的集合,因为它们的数据结构不一样,所以这个取出动作对象各不相同。直接在集合内部定义一个取出类(也是集合中的内部类)。

图片三pic_3.jpg

 

举例:电玩城的大容器

容器里面放置各种玩具。不同容器玩具的排列方式不一样,而每个容器都有一个夹子,当然,夹子也各不相同。这个夹子就相当于迭代器。被封装在容器内部。外面有个摇杆,这个摇杆就提供操作夹子的方式

5、两者有何区别:

在内存上有所不同,第一种在迭代器用完之后it对象还存在,占用着内存,而第二种迭代器在for循环完成之后就不存在了,它所占的内存直接被释放掉了

方式一:Iterator it = a1.iterator();

                  while(it.hasNext()){

                           sop(it.next());

                  }

方式二:for(Iterator it1 = a1.iterator();it1.hasNext();)

                  {

                           sop(it.next());

                  }

Collection

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

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

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

|----Vector:底层是数组数据结构。线程同步。被ArrayList替代了。

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

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

                           HashSet是如何保证元素唯一性呢?

                           是通过元素的两个方法,hashCodeequals来完成

                           如果元素的HashCode值相同,才会判断equals是否为true

                           如果元素的HashCode值不同,不会调用equals

注意:对于判断元素是否存在,以及删除操作,依赖的方法时元素的hashCodeequals方法。

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

      底层数据结构是二叉树

      保证元素唯一性的依据:compareTo方法return 0.

      TreeSet排序的第一种方式:

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

TreeSet排序的第二种方式:

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

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

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

41、             List

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

增:add(index,element)

      addAll(index,Collection)

删:remove(index)

改:set(index,element)

查:get(index);subList(from,to);

listIterator();

List集合特有的迭代器,ListIteratorIterator的子接口。在迭代时不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。

所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法时有限的,只能对元素进行判断,取出,删除的操作。如果想要其他的操作如添加、修改等,就需要使用子接口,ListIterator。该接口(ListIterator)只能通过List集合的listIterator方法获取。

示例代码:

package day28;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

import java.util.ListIterator;

publicclass ListDemo {

        publicstaticvoid method(){

                  ArrayList a1 =newArrayList();

                  a1.add("java01");

                  a1.add("java02");

                  a1.add("java03");

                  sop("a1:"+a1);

                  //在指定为置添加元素。

                  a1.add(1,"java09");

                  //删除指定位置的元素

                  //a1.remove(2);

                  //修改元素

                  a1.set(2,"007");

                  //通过角标获取元素

                  sop("get(1)"+a1.get(1));

                  //获取所有元素

                  for(int x=0;x<a1.size();x++){

                           sop("a1("+x+")"+a1.get(x));

                  }

                  for(Iterator it = a1.iterator();it.hasNext();){

                           sop("next"+it.next());

                  }

                  sop("a1:"+a1);

                  //通过indexOf获取对象的位置,如果对象不存在放回-1

                  sop("index="+a1.indexOf("java"));

                  //不包括角标位置为3的元素

                  List sub = a1.subList(1,3);

                  sop("sub="+sub);

        }

        publicstaticvoid iterator(){

                  //演示迭代器

                  ArrayList a1 =newArrayList();

                  a1.add("java01");

                  a1.add("java02");

                  a1.add("java03");

                  //在迭代的过程中,准备添加或者删除元素

                  /* ConcurrentModificationException

                   *当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

                   * */

                  /**

                   *对整个程序的理解:

                   *a1添加了三个元素,而it迭代器也有三个元素,你再加新的一个迭代器不知道

                   *再删一个更麻烦,迭代器本来认为有,而你给它删了,取不着,这就是一个问题?!

                   *解决问题的办法:要么全部用集合的方法;要么用迭代器的方法

                   * 

                   * */

                  //相当于将元素的引用放入到迭代器中,现在能操作元素的方法有两种,

                  //要么可以用集合的方法操作,要么用迭代器的方法操作,可是这两种操作

                  //的都是同一个元素。不能对同一组元素同时进行多种不同的操作,有可能

                  //引发并发修改异常(你在取,我在加,你到底去不去,搞不清楚)

                  Iterator it = a1.iterator();

                  while(it.hasNext()){

                           Object obj = it.next();

                           if(obj.equals("java01")){

                                    //a1.add("java008");//添加的动作,迭代器做不了

                                    it.remove();//java01的引用从集合中删除

                           }

                           sop("obj:"+obj);//结果有三个

                  }

                  /*为什么这两者有区别呢?

                   * remove是将元素的java01引用移除了,但是元素还在内存中

                   *而且元素java01还被obj引用,所以一个为3,一个为2

                   *但最终集合中的元素变了*/

                  sop(a1);//结果有两个

                  

        }

        publicstaticvoid listIterator(){

                  //演示列表迭代器

                  ArrayList a1 =newArrayList();

                  a1.add("java01");

                  a1.add("java02");

                  a1.add("java03");

                  sop(a1);

                  //只有list元素才具备这个功能,因为list元素有角标

                  ListIterator li = a1.listIterator();

                  while(li.hasNext()){

                           Object obj= li.next();

                           if(obj.equals("java02"))

                                    //li.add("java009");正常添加

                                   li.set("java007");//又可以修改

                  }

                  sop(a1);

                  while(li.hasPrevious()){

                           sop("pre:"+li.previous());

                  }

        }

        publicstaticvoid main(String args[]) {

                  //List特有方法演示

                  //method()

                  //iterator

                  iterator();

                  listIterator();

                  

                  

        }

        publicstaticvoid sop(Object obj){

                  System.out.println(obj);

        }

}

42、             Vector

ArrayListVector是一样的:

区别:

1ArrayList不是线程同步的,运行效率高;而Vector是线程同步的,运行效率低下。

2ArrayList(可变长度数组)默认容量为 10,当超过长度为10的元素后,在往里面添加的话,它就会new一个新的数组,长度为50%延长,变成15,将原来数组中的元素copy到新数组中来,再将新元素添加到后面去

3Vector长度也为10,当长度超过10的时候,它是100%延长,变成20.相比较而言,还是ArrayList好一些(理由:即能延长,又能节省空间,而vector比较浪费空间)

注意:在使用Vector的迭代器时,最好选用Enumeration,原因是:

Vector iterator listIterator方法所返回的迭代器是快速失败的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代器自身的 remove add方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生不确定行为的风险。Vector elements方法返回的 Enumeration不是快速失败的。

 

最重要的几个集合:

ArrayList     LinkedList            HashSet         HashMap

Vector独特方法的演示:

package day29;

/*

 *枚举就是Vector特有的取出方式。

 *发现枚举和迭代器很像

 *其实枚举和迭代器是一样的

 *因为枚举的名称以及方法的名称都过长。

 *所以被迭代器取代了。枚举郁郁而终了

 * */

import java.util.Vector;

import java.util.Enumeration;

publicclass VectorDemo {

        publicstaticvoid main(String args[]) {

                  Vector v =new Vector();

                  v.add("java01");

                  v.add("java01");

                  v.add("java01");

                  Enumeration en = v.elements();

                  while (en.hasMoreElements()) {

                           System.out.println(en.nextElement());

                  }

        }

}

43、             LinkedList

LinkedList:特有方法

addFirst( );

addLast( );

getFirst( );

getLast( );

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

removeFirst( );

removeLast( );

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

JDK1.6时出现了替换

offerFirst( )

offerLast( )

peekFirst( )

peekLast( )

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

pollFirst( )

pollLast( )

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

示例代码:

package day29;

import java.util.LinkedList;

publicclass LinkedListDemo {

        publicstaticvoid sop(Object obj){

                  System.out.println(obj);

        }

        publicstaticvoid main(Stringargs[]) {

                  LinkedList link =newLinkedList();

                  link.addLast("java01");

                  link.addLast("java02");

                  link.addLast("java03");

                  link.addLast("java04");

//                sop(link.getFirst());

//                sop(link.getLast());

//                sop(link.removeFirst());

//                sop(link.size());

                  while(!link.isEmpty()){

                           sop(link.removeFirst());

                  }

        }

}

44、             使用LinkedList模拟一个堆栈或者队列数据结构

堆栈:先进后出,如同被子。

队列:先进先出First in First out     FIFO如同一个水管

这种封装数据的作用:在开发的过程中,总有一些人为了使方法更容易理解,而选择封装这些数据,进而自定义与这个数据相关的操作,以便使开发更简单。

示例代码:

package day29;

import java.util.LinkedList;

class DuiLie{

    privateLinkedListlink;

    public DuiLie(){

             link =newLinkedList();

    }

    publicvoid myAdd(Object obj){

             link.addFirst(obj);

    }

    publicObject myGet(){

             returnlink.removeLast();//队列

             //return link.removeFirst();//堆栈

    }

    publicboolean isNull(){

             returnlink.isEmpty();

    }

}

publicclass LinkedListTest {

    publicstaticvoid main(String args[]) {

             DuiLie d1 =new DuiLie();

             d1.myAdd("java01");

             d1.myAdd("java02");

             d1.myAdd("java03");

             while(!d1.isNull()){

                      System.out.println(d1.myGet());

             }

    }

}

 

45、             去除ArrayList中重复的元素

package day29;

/**

 *去除ArrayList中重复的元素*/

import java.util.ArrayList;

import java.util.Iterator;

publicclass ArrayListTest {

        publicstaticvoid main(String args[]) {

                  ArrayList a1 =newArrayList();

                  a1.add("java01");

                  a1.add("java01");

                  a1.add("java02");

                  a1.add("java01");

                  a1.add("java02");

                  a1.add("java01");

                  a1.add("java03");

                  System.out.println(a1);

                  a1=singleElement(a1);

                  System.out.println(a1);

        }

        publicstaticArrayList singleElement(ArrayList a1){

                  //定义一个临时容器

                  ArrayList array =newArrayList();

                  Iterator it = a1.iterator();

                  /*在迭代时循环中next调用一次,就要hasNext判断一次*/

                  while(it.hasNext()){

                           Object obj = it.next();

                           if(!array.contains(obj)){

                                    array.add(obj);

                           }

                  }

                  return array;

        }

}

由于以上LinkedListArrayList都有相似的功能,在开发中应该使用哪个呢?

如果开发程序中对增加、删除操作的比较频繁的话,优先使用LinkedList;对之操作的不是很频繁的话,就应该选择ArrayList(只要元素不是特别多,ArrayList中增加、删除也是允许的)。当然,如果查询比较频繁的话,肯定是ArrayList比较划算。
-------android培训、java培训、期待与您交流! ----------
原创粉丝点击