黑马程序员.Android攻城狮.JAVA基础.1.7.Java集合

Java集合

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

1、集合的概念

        集合就是一个储存对象的动态数组,由于Java是面向对象进行操作的,所以对对象的存是非常重要的,所以就产生了集合的概念。
        数组虽然也可以储存对象,但是数组的长度是固定的,而集合长度是可以变化的,数组只能储存基本数据类型,集合可以储存任意类型对象。
        Java中的集合类主要用于保存、盛装其它数据(集合里只能保存对象,实际上保存的是对象的引用变量),因此集合类也被称为容器类。Java的集合类主要由Collection和Map两个接口派生出,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类,所有的集合类都位于java.util包下。集合有很多种类,其继承关系如下图所示:
                         
        由于数据的存储方式即数据结构不同,所以其使用方法及功能各不相同,所以就产生了各种类型的容器类型。

2、Collection接口

        Collection接口是Java集合框架的最大接口,但不能直接使用该接口,其主要子接口有:List、Set、Queue、SortedSet。
        Collection提供了很多方法,如:
                boolean  add(Object  o);用于向集合中添加元素
                boolean  addAll(Collection  c);将集合c里的所有元素添加到指定的集合里
                void  clear();清除集合里的所有元素
                bolean  contains(Object  o);返回集合里是否包含指定元素
                boolean  containsAll(Collection  c);返回集合里是否含集合c里的所有元素
                boolean  isEmpty();返回集合是否为空。当集合长度为0时,返回true;否则返回false
                Iterator  iterator();返回一个Iterator对象,用于遍历集合里的元素
                boolean  remove(Object  o);删除集合中指定元素
                boolean  removeAll(Collection  c);从该集合中删除集合c里包含的元素
                boolean  retainAll(Collection  c);从该集合中删除集合c里不包含的元素
                int  size();返回集合里元素的个数,即集合的长度
                Object[]  toArray();该方法把集合转换成一个数组,所有集合元素变成对应的数组

        (1) Iterator接口

                Java集合提供了一个标准的接口实现集合中元素的输出操作,主要有四种常见输出操作:
                (1) Iterator    (2) ListIterator    (3) Enumeration    (4) foreach
                而以上四种输出以Iterator为操作的标准,该接口是最常使用的输出形式。
                迭代器的输出原理为:将元素一个一个进行判断,判断其是否有内容,如果有则取出。
                Iterator中常用的方法如下:
                        boolean  hasNext();如果被迭代的集合元素还没有被遍历,则返回true
                        Object  next();返回集合里下一个元素
                        void  remove();删除集合里上一次next方法返回的元素。
                以下代码为Iterator输出的示例代码:
               
import java.util.ArrayList;
import java.util.Iterator;

public class Demo {
	public static void main(String[] args){
		ArrayList a = new ArrayList();
		a.add("abc");
		a.add("def");
		a.add("ghi");
		for(Iterator it = a.iterator(); it.hasNext(); ){
			System.out.println(it.next());
		}
	}
}

        (2) List接口

                List接口是Collection的子接口,其中可以保存重复的内容,其主要子类有ArrayList、LinkedList等。
                与Collection不同的是,在List接口中扩充了Collection接口的一些主要方法,如:
                        boolean  add(index, element);向指定的位置添加指定的元素
                        boolean  addAll(index, Collection);向指定的位置开始,添加多个元素
                        boolean  remove();移除元素(还有各种重载版本)
                       
E  set(index, element);将指定位置的元素修改为element
                        E  get(index);由索引获取该位置上的元素
                        List  subList(from, to);截取子List,从from开始到to结束,包含头,不含尾
                        ListIterator  listIterator();List集合特有的迭代器
                ListIterator是List集合特有的迭代器,是Iterator的子接口,在迭代时,不可以通过集合对象的方法操作
        集合中的元素,因为会发生异常,所以在只能用迭代器的方法操作元素,如判断、取出、删除操作,若想进
        行添加、修改等操作,就需要是用该ListIterator等子接口来实现,ListIterator的常用方法有:
                        void  add(E  e);将指定的元素插入列表(可选操作)
                        boolean  hasNext();以正向遍历列表时,如果列表迭代器有多个元素,则返回 true 
                        boolean  hasPrevious();如果以逆向遍历列表,列表迭代器有多个元素,则返回 true
                         E  next();返回列表中的下一个元素
                         int  nextIndex();返回对 next 的后续调用所返回元素的索引 
                        E  previous();返回列表中的前一个元素
                        int  previousIndex();返回对 previous 的后续调用所返回元素的索引
                        void  remove();从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)
                        void  set(E  e);用指定元素替换 next 或 previous 返回的最后一个元素(可选操作) 

                (a) ArrayList接口
                        ArrayList是List的子类,可以直接通过对象的多态性为List接口实例化,该类底层使用的数据结
                构为数组,由于使用数组结构,具有角标,所以查询数据速度很快,增加及删减稍慢。
                (b) LinkedList接口
                        LinkedList表示的是一个链表的操作类,增加及删减元素很快,查询很慢。
                        LinkedList的特有方法有:
                        void addFirst(E e);将指定元素插入此列表的开头 
                        void addLast(E e);将指定元素添加到此列表的结尾
                        E getFirst();返回此列表的第一个元素。获取元素,不删除元素
                        E getLast();返回此列表的最后一个元素
                        E removeFirst();移除并返回此列表的第一个元素。获取元素,但是删除元素
                        E removeLast();移除并返回此列表的最后一个元素
                        E peekFirst();获取但不移除此列表的第一个元素;如果此列表为空,则返回 null 
                        E peekLast();获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null
                        E pollFirst();获取并移除此列表的第一个元素;如果此列表为空,则返回 null
                        E pollLast();获取并移除此列表的最后一个元素;如果此列表为空,则返回 null
                        boolean offerFirst(E e);在此列表的开头插入指定的元素
                        boolean offerLast(E e);在此列表末尾插入指定的元素
                (c) Vetcor接口
                        在JDK1.0时即存在该类,其底层数据结构为数组,其增删改查都比较慢,被ArrayList等代替。
                所以要根据实际需要选择合适的集合。

               示例代码: 使用LinkedList模拟一个堆栈及队列结构
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;

//使用Arraylist模拟一个堆栈或者队列结构
public class Queue {
	public static void main(String[] args){
		QueueDemo q = new QueueDemo();
		q.myAdd("a");
		q.myAdd("b");
		q.myAdd("c");
		q.myAdd("d");
		while(!q.isNull()){
			System.out.println(q.myGet());
		}
	}
}
class QueueDemo{
	private LinkedList link;
	QueueDemo(){
		link = new LinkedList();
	}
	public void myAdd(Object obj){
		link.addFirst(obj);
	}
	public Object myGet(){
		return link.removeLast();//使用此行代码则为先进先出,即队列
	//	return link.removeFirst();//使用此行代码则为先进后出,即堆栈
	}
	public boolean isNull(){
		return link.isEmpty();
	}
}
        

       (3) Set接口

                Set接口也是Collection的子类,与List接口不同,Set接口不能加入重复的元素,其主要方法
        与Collection基本一致。 Set的常用子类有HashSet与TreeSet。
                (a) HashSet
                HashSet是Set的一个子类,主要特点是:不能有重复的元素,数据采用散列存储的方式,底层数据
        结构是hash表。
               由于该类不能重复的存储元素,所以需要对需要存储的对象进行比较验证以保证对象的唯一性,
        证主要依靠两个方法: hashCode()与equals(),首先比较hash值区分是否为同一对象,若值不同 则认为
        这两个对象是不同的,即可开辟空间存储对象。若比较hash值一样,则继续用equals方法比较是否是同
        一个对象,若不是则存储,若相同,则只存储一个对象,这样就保证了对象的唯一性。
                有时我们需要存储我们自定义的类的对象,所以按照默认的equals方法比较两个对象是否相同是不
        够的,所以就需要自定义equals()方法覆写Object提供的默认比较方法来比较对象。
                对于判断元素是否存在以及删除等操作也都是依赖于元素的hashcode()和equals()方法。
               注意:在实际的开发中为了区分是否为同一对象问题,就需要在编写类时按照需求覆写hashcode()、
        equals()以及toString()方法。

                (b) TreeSet
                TreeSet也是Set接口的子类,该类可以对集合中的元素进行指定顺序的排序,并且线程是不同步的。
        TreeSet底层的数据结构为二叉树,用于对TreeSet集合进行元素的指定顺序排序,排序需要依据元素自身
        具备的比较性,如果元素不具备比较性,在运行时会发生ClassCastException异常。所以需要元素实现
        Comparable接口,强制让元素具备比较性,复写compareTo()方法。依据compareTo()方法的返回值,确
        定元素在TreeSet数据结构中的位置。
                TreeSet方法保证元素唯一性的方式:参考比较方法的结果是否为0,如果为0视为两个对
象重复。
               注意:在进行比较时,如果判断元素不唯一,比如,同姓名,同年龄,才视为同一个人。
                在判断时,需要分主要条件和次要条件,当主要条件相同时,再判断次要条件,按照次要条件排序。
                TreeSet集合排序有两种方式,Comparable和Comparator区别:
                (a) 让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法,示例如下:
import java.util.Iterator;
import java.util.TreeSet;

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 s = (Student)obj;
		if(this.age > s.age)
			return 1;
		if(this.age == s.age){
			return this.name.compareTo(s.name);
		}
		return -1;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
}
public class TreeSetDemo {
	public static void main(String[] args){
		TreeSet t = new TreeSet();
		t.add(new Student("AAAA",23));
		t.add(new Student("AABB",13));
		t.add(new Student("AACC",21));
		for(Iterator it = t.iterator(); it.hasNext(); ){
			Student s = (Student)it.next();
			System.out.println(s.getName()+" "+s.getAge());
		}	
	}
}
                (b) 让集合自身具备比较性,即:让集合初始化时就具备了比较性,需要定义一个实现了Comparator接口
        的比较器,并覆盖compare方法,并将该类对象作为实际参数传递给TreeSet集合的构造函数, 示例如下:
                修改(a)方法中的部分代码,并添加一个比较类。
public class TreeSetDemo {
	public static void main(String[] args){
		TreeSet t = new TreeSet(new MyCompare());
		t.add(new Student("ADAA",23));
		t.add(new Student("ABAB",13));
		t.add(new Student("AGBB",13));
		t.add(new Student("AACC",21));
		t.add(new Student("BBDD",27));
		for(Iterator it = t.iterator(); it.hasNext(); ){
			Student s = (Student)it.next();
			System.out.println(s.getName()+" "+s.getAge());
		}	
	}
}
class MyCompare implements Comparator{
	public int compare(Object o1, Object o2){
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
		int num = s1.getName().compareTo(s2.getName());
		if(num==0)
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		return num;
	}
}
                由以上示例代码可知,使用Comparator对两个对象进行比较更加实用,较为灵活。

3、Map接口

        之前所有的集合类都是单值的,即每一次只能操作一个对象,而Map集合能操作一对对象,Map中每个元素
都使用key-value的形式储存在集合中。
        特点:该集合存储键值对,一对一对往里存,而且要保证键的唯一性,不允许出现重复。
        接口的常用子类有:HashTable、HashMap、TreeMap
                (1) HashTable           
                该类是一个旧的子类,在JDK1.0时推出,采用同步处理方式,性能较低,且属于线程安全类型,不允许
        将key设为null,现在使用较少。
                (2) HashMap 
                在JDK1.2版本后推出,采用异步处理方式,其性能较高且属于非线程安全类,还允许将key设为null。
                (3) TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序。
        Map接口的主要方法有:
                (1)  添加。
                  put(K key, V value);将键值存储到集合,put方法的返回值,一般情况下是null,但是如果存储了重复的
        键,替换原来老键的值,put方法的返回值就是被替换后的值
                 putAll(Map<? extends K,? extends V> m);存储一批键值
                (2)  删除。
                 void  clear();删除所有键值
                 V  remove(Object  key);根据键删除键值,若键存在,删除该键且返回值,若键不存在,返回null
                (3)  判断。
                 boolean  containsKey(Object  key);判断该集合中是否有这个键
                 boolean  containsValue(Object  value);判断该集合中是否有这个值
                 boolean  isEmpty();判断集中中是否有键值
                (4)  获取。
                 V get(Object key);通过键获取值,若键存在,删除该键且返回值,若键不存在,返回null
                 int size();获取集合中键值对的数量
                 Collection<V> values();以集合的方式返回集合中包含的值
                 (5) 输出Map所有元素
                由于Map接口中每个位置存放的时一对值,而Iterator每次只能找到一个值,所以Map接口不能向其它
        单值集合一样可以直接用Iterator输出,需要使用以下两种Iterator方式输出。
               
(a) 使用keySet()方法
                将Map集合中所有的键存入到Set中,然后使用Set的迭代器以及Map的get()方法获取键值。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

class Person
      
      
       
       {
	private T name;
	private R age;
	Person(T name, R age){
		this.name = name;
		this.age = age;
	}
	public T getName(){
		return name;
	}
	public R getAge(){
		return age;
	}
}
public class Map {
	public static void main(String[] args) {
		HashMap
       
       
        
         m = new HashMap
        
        
         
         ();
		m.put("AAA", 25);
		m.put("AAB", 22);
		m.put("BCA", 21);
		m.put("DBA", 28);
		Set
         
         
          
           keyset = m.keySet();
		for(Iterator
          
          
            it = keyset.iterator(); it.hasNext(); ){ String key = it.next(); Integer value = m.get(key); System.out.println("key:"+key+" value:"+value); } } } 
          
         
         
        
        
       
       
      
      
                (b) 使用entrySet()方法及Map.Entry接口
                Map.Entry是Map内部的一个接口,专门用来保存key-value的内容,它使static声明的内部接口(定义为内
        部接口的原因是它保存的时key-value之间的映射关系,没有Map就没有映射关系),可以由外部调用,其中的
        方法有:
                public  boolean equals(Object o);对象比较
                 public  K  getKey();取得key
                 public  V  getValue();取得value
                 public  int  hashCode();返回hash码
                public  V  setValue(V  Value);设置value的值 
                示例代码:描述学生,将学生作为键,地址作为值保存在Map中,并获取Map中的每个元素

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

class Student implements Comparable
     
     
      
      {
	private String name;
	private int age;
	Student(String name, int age){
		this.name = name;
		this.age = age;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
	public String toString(){
		return name+" "+age;
	}
	public int hashCode(){				//覆写hashCode方法
		return name.hashCode()+age*23;
	}
	public boolean equals(Object obj){	//覆写equals方法,判断两个对象是否是同一个
		if(!(obj instanceof Student))
			throw new RuntimeException("类型不匹配");
		Student s = (Student)obj;
		return this.name.equals(s.name) && this.age==s.age;
	}
	@Override
	//若该类需要存放到TreeMap等二叉树排序的集合中,就需要编写排序比较方法
	public int compareTo(Student s) {	
		int num = new Integer(this.age).compareTo(new Integer(s.age));
		if(num==0)
			return this.name.compareTo(s.name);
		return num;
	}
}
public class FanXing{
	public static void main(String[] args){
		Map
      
      
       
        m = new HashMap
       
       
        
        (); 
		m.put(new Student("hao2", 27), "Hei");
		m.put(new Student("hao1", 23), "Bei");
		m.put(new Student("hao3", 28), "Tian");
		m.put(new Student("hao1", 23), "Tian");
		m.put(new Student("hao4", 21), "Shang");
		Set
        
        
         
         
           > set = m.entrySet(); for(Iterator 
           
           
             > it = set.iterator(); it.hasNext(); ){ Map.Entry 
            
              map = it.next(); Student student = map.getKey(); String addr = map.getValue(); System.out.println(student+" "+addr); } } } 
             
            
           
         
        
        
       
       
      
      
     
     
        

---------- Windows Phone 7手机开发、.Net培训、期待与您交流! ----------
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值