黑马程序员——Java基础---集合

来源:互联网 发布:163 smtp ssl 端口 编辑:程序博客网 时间:2024/04/28 12:49

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

JAVA集合类

Collection

 ├List

 │├LinkedList

 │├ArrayList

 │└Vector

 │ └Stack

 └Set

TreeSet

HashSet

LinkedHashSet

Map

 ├TreeMap

 └HashMap

LinkedHashMap

Collection接口

Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如ListSet

List接口

List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。和下面要提到的Set不同,List允许有相同的元素。

除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个 ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素, 还能向前或向后遍历。

实现List接口的常用类有LinkedListArrayListVectorStack

代码示例:

/*Collection|--List:元素是有序的,元素可以重复。因为该集合体系有索引。|--ArrayList:底层数据结构使用的是数组结构。特点:查询速度快。但是增删稍慢。线程不同步|--LinkedList:底层使用的是链表数据结构。特点:增删速度快,查询稍慢。|--Vector:底层是数组结构。线程同步,被ArrayList替代了。|--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方法获取。*/import java.util.*;class ListDemo{public static void method(){ArrayList al = new ArrayList();//添加元素al.add("java01");al.add("java02");al.add("java03");sop("原集合:"+al);// al.add(1,"java04");//删除指定位置的元素。// al.remove(2);//修改元素。// al.set(2,"java05");//通过角标获取元素。// sop("get(1):"+al.get(1));// sop(al);// for(int i=0;i<al.size();i++)// {// System.out.println("al("+i+")"+al.get(i));// }// Iterator it = al.iterator();// while(it.hasNext())// {// sop("next="+it.next());// }//通过indexOf获取对象的位置。sop("index="+al.indexOf("java02"));List sub = al.subList(1,3);sop("sub="+sub);}public static void Iterator(){//演示迭代器。ArrayList al = new ArrayList();//添加元素al.add("java01");al.add("java02");al.add("java03");ListIterator li = al.listIterator();while(li.hasNext()){Object obj = li.next();if(obj.equals("java02"))li.add("java04");}sop("hasNext:"+li.hasNext());sop("hasPrevious:"+li.hasPrevious());sop(al);/* //在迭代过程中,准备添加或者删除元素。Iterator it =al.iterator();while(it.hasNext()){Object obj = it.next();if(obj.equals("java02")){//将java02的引用从集合中删除。it.remove();}sop("obj="+obj);}  */}public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args){// method();Iterator();}}

LinkedList

LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的getremoveinsert方法在 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。

注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List

List list = Collections.synchronizedList(new LinkedList(...));

代码示例:

/*LinkedList:特有方法:addFirst();addLast();获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException。getFirst();getLast();获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException。removeFirst();removeLast(); 在JDK1.6出现了替代方法。offerFirst();offerLast();获取元素,但不删除元素。如果集合中没有元素,会返回null。peekFirst();PeekLast();获取元素,但是元素被删除。如果集合中没有元素,会返回null.pollFirst();pollLast(); */import java.util.*;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);// sop(link.getFirst());// sop(link.getLast());// sop(link.removeFirst());// sop(link.removeLast());while(!link.isEmpty()){sop(link.removeFirst());}}}

ArrayList

ArrayList实现了可变大小的数组。它允许所有元素,包括nullArrayList没有同步。

sizeisEmptygetset方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。

每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法 并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。和LinkedList一样,ArrayList也是非同步的(unsynchronized)。

代码示例:

import java.util.*;/* 1,add方法的参数类型是Object。以便于接收任意类型对象。 2,集合中存储的都是对象的引用(地址)。  什么是迭代器? 迭代器其实就是集合取出元素的方式。 */class CollectionDemo{public static void method_get(){ArrayList al = new ArrayList();al.add("java01");al.add("java02");al.add("java03");al.add("java04");//获取迭代器,用于取出集合中的元素。Iterator it1 = al.iterator();while(it1.hasNext()){sop(it1.next());}//使用for循环节约资源for(Iterator it2 = al.iterator();it2.hasNext();){sop(it2.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中只会保留和al2中相同的元素。//al1.retainAll(al2);al1.removeAll(al2);sop("al1:"+al1);sop("al2:"+al2);}public static void base_method(){//创建一个集合容器。使用Collection接口的子类,ArrayListArrayList al = new ArrayList();//1,添加元素。al.add("java01");al.add("java02");al.add("java03");al.add("java04");//打印原集合。sop("原集合:"+al);//2,获取个数。sop("size:"+al.size());//3,删除元素。al.remove("java02");//清空集合。al.clear();//4,判断元素。sop("java03是否存在:"+al.contains("java03"));sop("集合是否为空:"+al.isEmpty());//打印改变后的集合。sop(al);}public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args){method_get();// base_method();// method_2();}}

Vector

Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和 ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了 Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出 ConcurrentModificationException,因此必须捕获该异常。

Stack 

Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的pushpop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

Set接口

Set是一种不包含重复的元素的Collection,即任意的两个元素e1e2都有e1.equals(e2)=falseSet最多有一个null元素。很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。

请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。

HashSet代码示例:

/* |--Set:元素是无序(存入和取出的顺序不一定一致)。元素不可以重复。|--HashSet:底层数据结构是哈希表。HashSet是如何保证元素唯一性呢?是通过元素的两个方法,hashCode和equals来完成。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals。注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。|--TreeSet:Set集合的功能和Collection是一致的。 */ import java.util.*;class HashSetDemo{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args){HashSet hs = new HashSet();sop(hs.add("java01"));sop(hs.add("java01"));hs.add("java02");hs.add("java03");hs.add("java04");Iterator it = hs.iterator();while(it.hasNext()){sop(it.next());}}}

TreeSet代码示例:
/*Set:无序,不可以重复。|--HashSet:数据结构是哈希表。线程是不同步的。保证元素唯一性的依据:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法是否为true。|--TreeSet:可以对Set集合中的元素进行排序。底层数据结构是二叉树。保证数据唯一性的依据:compareTo方法return 0;TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也称为元素的自然顺序,或者叫默认顺序。TreeSet的第二种排序方式。当元素自身不具备比较性时,或者具备比较性不是所需要的。这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。需求:往TreeSet集合中存储自定义对象学生。想按照学生的年龄进行排序。记住:排序时,当主要条件相同时,一定要判断一下次要条件。 */ import java.util.*;class TreeSetDemo{public static void main(String[] args){TreeSet ts = new TreeSet();ts.add(new Student("lisi01",20));ts.add(new Student("lisi02",21));ts.add(new Student("lisi03",21));Iterator it = ts.iterator();while(it.hasNext()){Student stu = (Student)it.next();System.out.println(stu.getName()+"..."+stu.getAge());}}}class Student implements Comparable//该接口强制让学生类具备比较性。{private String name;private int age;Student(String name,int age){this.name = name;this.age = age;}public int compareTo(Object obj){if(!(obj instanceof Student))throw new RuntimeException("不是学生对象");Student stu = (Student)obj;System.out.println(this.name+"..compareto.."+stu.name);if(this.age>stu.age)return 1;if(this.age==stu.age){return this.name.compareTo(stu.name);}return -1;}public String getName(){return name;}public int getAge(){return age;}}

Map接口

请注意,Map没有继承Collection接口,Map提供keyvalue的映射。一个Map中不能包含相同的key,每个key只能映射一个 valueMap接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

Map接口代码示例:

/* Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。1.添加。put(K key,V value)putAll(Map<? extends K,? extends V> m)2.删除。clear()3.判断。containsValues(Object value)containsKey(Object key)isEmpty()4.获取。get(Object key)size()values()entrySet()keySet()Map:|--Hashtable:底层是哈希表数据结构,不可以存入null键和null值。该集合是线程同步的。JDK1.0 效率低。|--HashMap:底层是哈希表数据结构,允许使用null键和null值。该集合是线程不同步。JDK1.2 效率高。|--TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序。Map和Set很像。其实Set集合底层使用了Map集合。 */import java.util.*;class MapDemo{public static void main(String[] args){Map<String,String> map = new HashMap<String,String>();//添加元素。如果出现添加相同的键,那么后添加的值会覆盖原有的键对应的值//并put方法会返回被覆盖的值。System.out.println(map.put("01","zhangsan1"));System.out.println(map.put("01","zhangsan4"));map.put("03","zhangsan3");System.out.println("containsKey:"+map.containsKey("02"));// System.out.println("remove:"+map.remove("02"));map.put("04",null);//可以通过get方法的返回值来判断一个值是否存在,通过返回null来判断。System.out.println("get:"+map.get("04"));//获取map集合中所有的值Collection<String> coll = map.values();System.out.println(coll);System.out.println(map);}}

HashMap

基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(get 和 put)提供稳定的性能。

TreeMap

基于二叉树的Map接口的实现。线程不同步,可以用于给map集合中的键进行排序。由TreeMap类实现的Map集合,不允许键对象为null,因为集合中的映射关系是根据键对象按照一定顺序排列的。

Map的两种取出方式代码示例:

/* map集合的两种取出方式:1.Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。所以可以以迭代方式取出所有的键,再根据get方法,获取每一个键对应的值。Map集合的取出原理:将map集合转成set集合,再通过迭代器取出。2.Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到set集合中,而这个关系的数据类型就是:Map.Entry */import java.util.*;class MapDemo2{public static void main(String[] args){Map<String,String> map = new HashMap<String,String>();map.put("01","lise1");map.put("02","lise2");map.put("03","lise3");map.put("04","lise4");//将Map集合中的映射关系取出。存入到Set集合中。Set<Map.Entry<String,String>> entrySet = map.entrySet();Iterator<Map.Entry<String,String>> it = entrySet.iterator();while(it.hasNext()){Map.Entry<String,String> me = it.next();String key = me.getKey();String value = me.getValue();System.out.println(key+":"+value);}/* //先获取map集合的所有键的Set集合,keySet();Set<String> keySet = map.keySet();//有了Set集合。就可以获取迭代器。Iterator<String> it = keySet.iterator();while(it.hasNext()){String key = it.next();//有了键可以通过map集合的get方法获取其对应的值。String values = map.get(key);System.out.println("key:"+key+",values:"+values);} */}}
总结

面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。在学习集合中,从底层的数据结构又分为不同的集合存储。所以在学习集合的时候也需要对计算机的数据结构有所了解。不过集合内容是挺多的,还需要经常回顾学习。

0 0
原创粉丝点击