黑马程序员——集合学习笔记(一)

来源:互联网 发布:wiki全球软件发展趋势 编辑:程序博客网 时间:2024/05/16 17:15

------- android培训java培训、期待与您交流! ----------

集合容器顶层接口:Collection

常用子接口:ListSet

常用实现类:ArrayListLinkedListVectorHashSetTreeSet

 

为什么会出现这么多的容器呢?

因为每一个容器对数据的存储方式都有不同。

这个存储方式称之为:数据结构。

 

Collection:

class CollectionDemo{public static void main(String[] args){//创建一个集合容器。使用Collection接口的子类。ArrayListArrayList al = new ArrayList();//1,添加元素。al.add(“java01”);//add(Object obj),参数接收Object,以便于接收任意类型的对象al.add(“java02”);//集合中存储的都是对象的引用(地址),而不是对象本身。al.add(“java03”);al.add(“java04”);//2,获取个数。集合长度。sop(“size:”+al.size());//3,删除元素。al.remove(“java02”);//删除java02的元素//al.clear();//清空集合。//4,判断元素。sop(“java03是否存在:”+al.contains(“java03”));//判断集合元素是否存在sop(“集合是否为空?”+al.isEmpty());//判断集合是否为空(也可用size是否为0判断)。//5,交集ArrayList al2 = new ArrayList();al2.add(“java01”);al2.add(“java02”);al2.add(“java05”);al2.add(“java06”);al.reatainAll(al2);//al中只保留与al2交集的部分元素。al.removeAll(al2)//al 中去除与al2交集的那部分元素。Iterator it = al.iterator();//获取迭代器接口Iterator的子类对象,用于取出集合中的元素。while(it.hasnext()){//循环判断迭代器中是否还有元素sop(it.next());//打印下一个迭代器中的元素。}}public static void sop(Object obj){System.out.println(obj)}}

迭代器:集合的取出元素的方式。

*每种容器由于其数据结构的差异,所以取出元素的方式都不同,因此每个容器都会在其内部建立一个内部类,用于取出元素。虽然每种容器的取出方式都不同,但是都有共性内部,就是判断和取出,那么可以将这些共性抽取。由此诞生了一个接口,就是Iterator。集合对象通过iterator()方法获取此接口的子类对象。

 

*下面两段代码的区别:

一:

Iterator it = al.iterator();while(it.hasNext()){sop(it.next);}

二:

for(Iterator it = al.iterator; it.hasNext(); ){sop(it.next());}

得到的结果相同,但是第二段代码对内存更加优化,因为it作为for的局部变量,在for循环迭代结束之后就马上被释放。

 

Collection

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

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

 

List:

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

增:add(index, element)

         addAll(index,Conllection);

删:remove(index);

改:set(index,element);

查:get(index);

         sublist(from,to);

         listIterator();

class ListDemo{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args){ArrayList al = new ArrayList();//添加元素al.add(“java01”);al.add(“java02”);al.add(“java03”);}sop(“原集合是:”+al);//在指定位置添加元素。al.add(1,”java09”);sop(al);//删除指定位置元素。al.remove(2);//修改指定位置的元素。al.set(2,”java007”);//通过角标获取元素。al.get(1);//获取所有元素。for(int x=0; x<al.size(); x++){sop(al.get(x));}//通过indexOf获取对象的位置sop(al.indexOf(“java02”));//获取子集合List sub = al.subList(1,3);sop(“sub=”+sub);//*列表迭代器listIterator();//例:在迭代过程中,准备添加或者删除元素。Object obj = it.next();if(Obj.equals(“java02”)){//al.add(“java008”);//正在用迭代器取出的过程中,对集合进行了添加操作,此行为称为并发访问,出现并发修改异常。it.remove();//使用迭代器自己的去除元素方法,可以正常去除集合元素。}sop(“obj=”obj);//以上的iterator迭代器只有移除元素的功能,出现了局限性,因此诞生了List集合特有的迭代器:ListIterator。//ListIterator是Iterator的子接口。可以对集合进行添加、修改等操作。//该接口只能通过List集合的listIterator()方法获得。ListIterator li = al.listIterator();while(li.hasNext()){Object obj = li.next();if(obj.equals(“java02”)){li.add(“java009”);}}sop(al);//ListIterator特性:判断前面是否有元素:li.hasPrevious();//遍历之后,再往前反向遍历集合:while(li.hasPrevious()){sop(li.previous());}}}

List

   |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快,但是增删稍慢(元素越多越明显),默认长度为10,超过时50%延长。

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

   |--Vector:底层是数组数据结构。与ArrayList功能基本相同,于jdk1.2版本之前广泛使用(1.2版本后出现ArrayList),特点:Vector是同步的。但是ArrayList线程不同步。多线程时,通常也会使  用ArrayList加锁。因此在1.2版本后,被ArrayList所替代。默认长度为10,超过时100%延长。

 

Vector特有的东西:枚举

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

class VectorDemo{public static void main(String[] args){Vector v = new Vector();v.add(“java01”);v.add(“java01”);v.add(“java01”);v.add(“java01”);Enumeration en = v.elements();//此方法可以获得Vector集合的枚举对象。while(en.hasMoreElements()){System.out.println(en.nextElement());}}}

 

LinkedList:

特有方法:addFirst();addLast();getFirst();getLast();removeFirst();removeLast();

class LinkedListDemo(){public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args){LinkedList link = new LinkedList();link.addLast(“java01”);link.addLast(“java02”);link.addLast (“java03”);link.addLast (“java04”);sop(link.getFirst());//get方法,获取元素,但不删除元素sop(link.removeFirst());//remove方法,获取元素,但是元素被删除。sop(link.pollFirst())//jdk1.6版本出现,poll方法,与remove方法功能相同,区别在于当没有元素时,此方法返回null,而remove或者get方法抛出NoSuchElementException异常。sop(link.peekFirst())//与poll方法类似,为get方法的替代。sop(link.offerFirst())//与poll方法类似,为add方法的替代。}}

 

*List集合判断元素是否相同,无论是contains()方法还是remove()方法,依据的都是元素的equals()方法。

 

Set:

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

   |--TreeSet

 

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

 

哈希表:对象调用hashcode()方法时返回对象哈希值,当哈希值相同时,再调用equals()方法判断是否是同一个对象。如果哈希值相同、不是一个对象时,会在该地址后顺延,添加此对象。如果哈希值不相同,则将哈希值单独放在一个位置上,不比较是否是同一个对象。

 

HashSet是通过元素的两个方法来保证元素的唯一性:hashCodeequals

如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashhCode值不同,则不会调用equals

 

HashSet集合中存入自定义对象,姓名和年龄相同视为同一个人,重复元素:

class Person{//自定义Person类private String name;private int age;Person(String name,int age){this.name = name;this.age = age;}public int hashCode(){//根据哈希表的数据结构,重写hashCode()方法。 //return 60;//第一种修改方法,将所有被HashSet添加进的元素设置相同的哈希值,就可以调用equals()方法判断是否是相同元素了。return name.hashCode() + age;//第二种修改方法,由于String类有自己的hashCode()方法,先算出姓名的哈希值与年龄相加作为元素哈希值,再去比较,这样在哈希值判断的层面就把明显的不同元素判断出来,可以省下很多equals()方法的比较。比第一种方法效率更高。}public Boolean equals(Object obj){//按照题目所给相同条件,当姓名和年龄相同时,视为是同一个对象。if(!(obj instanceof Person)){return false;}person p = (Person)obj;return this.name.equals(p.name) && this.age == p.age;}public String getName(){return name;}public int getAge(){return age;}}class HashSetTest{public static void sop(){System.out.println(obj);}public static void main(String[] args){HashSet hs = new HashSet();hs.add(new Person(“a1”, 11));hs.add(new Person(“a2”, 12));hs.add(new Person(“a3”, 13));hs.add(new Person(“a2”, 12));hs.contains(new Person(“a2”,12));hs.remove(new Person(“a3”,13);//对于判断元素是否存在以及删除等操作,依赖的方法也是元素的hashCode()和equals()方法。Iterator it = hs.iterator();while(it.hasNext()){//遍历集合,查看结果。Person p = (Person)it.next();sop(p.getName() + “::”+ p.getAge);}}}

上述代码证实了ArrayListHashSet的另一处不同:ArrayList判断元素存在以及删除等操作,只依赖equals,而HashSet是先依赖hashCode(),再依赖equals,原因就是数据结构的不同,HashSet的哈希表的特点。