Java基础之集合框架

一、集合框架概述

集合的概念
        面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
数组和集合类有何不同
        数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
集合类的特点
        集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
集合框架的构成及分类

关系概括:Collection和Map是Java集合框架(Java Collections Framework)的两个主要成员。
                    List和Set是由Collection接口派生的两个接口,Collection、List、Set、Map都是接口,不能被实例化
下面是Collection和Map两个集合的主要接口及实现类关系以及特点
Collection          接口的接口   是对象的集合 
      |--List            子接口      元素是有序的,元素可以重复。因为该集合体系有索引
      |    |--ArrayList       接口实现类   底层的数据结构使用的是数组;线程不安全。特点:查询、修改快,增删慢;
      |     |-- LinkedList     接口实现类   底层使用的是链表数据结构;线程不安全。特点:增删的速度快,查询速度慢
      |     |-- Vector           接口实现类   底层是数组数据结构;线程安全,无论增删改查都慢,被ArrayList替代 
      |
      |--Set            子接口     元素是无序的,并且元素不可以重复
           |--HashSet    接口实现类    底层数据结构是哈希表,线程是不安全的
           |--TreeSet     接口实现类    底层数据结构是二叉树,可以对集合中的元素进行排序
 
Map                接口      键值对的集合 
      |--Hashtable:接口实现类:底层是哈希表数据结构,不可以存入null键null值,线程安全;效率低
      |--HashMap: 接口实现类:底层是哈希表数据结构,允许存入null键null值,线程不安全;效率高
      |--TreeMap:  接口实现类:底层是二叉树数据结构,线程不安全,可以用于给map集合中的键进行排序

二、Collection集合

Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。

Collection定义了集合框架的共性功能。
增加
        add(e);向集合中添加元素
        addAll(collection);将指定 collection 中的所有元素都添加到此 collection 中
删除
        remove(e);从此 collection 中移除指定元素的单个实例,如果存在的话
        removeAll(collection);移除此 collection 中那些也包含在指定 collection 中的所有元素
        clear();移除此 collection 中的所有元素
判断
        contains(e);如果此 collection 包含指定的元素,则返回true
        isEmpty();  如果此 collection 不包含元素,则返回 true
获取
        iterator();返回在此 collection 的元素上进行迭代的迭代器。
        size();返回此 collection 中的元素数。
获取交集。
        retainAll();获取交集。。
集合变数组。
        toArray();
迭代器
迭代是取出集合中元素的一种方式。因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。
用法:
1、使用for循环遍历
for(Iterator iter = iterator();iter.hasNext();  )
{
	System.out.println(iter.next());
}
2、使用while循环遍历
Iterator iter = l.iterator();
while(iter.hasNext())
{
	System.out.println(iter.next());
}

List集合

List集合元素是有序的,元素可以重复。因为该集合体系有索引。
List的特有方法

       add(index,element);在列表的指定位置插入指定元素
       addAll(index,Collection);将指定 collection 中的所有元素都插入到列表中的指定位置

       remove(index);移除列表中指定位置的元素

       set(index,element);用指定元素替换列表中指定位置的元素

       get(index);返回列表中指定位置的元素
       subList(from,to);返回列表中指定的fromIndex(包括 )和toIndex(不包括)之间的部分视图
       listIterator();返回List集合特有的迭代器
注意:在使用listIterator迭代时候,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常
所以,在迭代时,只能用迭代器的方法操作元素,可是Iterator的方法是有限的,只能对元素进行判断、取出、删除操作。如果想要其他的操作如添加,修改等就需要使用其子接口ListIterator。该接口只能通过List集合的listIterator()方法获取。

ArrayList

ArrayList:底层的数据结构使用的是数组结构:特点,查询、修改速度快,增删慢;线程不同步
它是List集合中最常用的一个实现类 
代码示例:
public class ListDemo {
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void main(String[] args) {
		ArrayList al=new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		
		ListIterator li=al.listIterator();
		while(li.hasNext()){
			Object obj=li.next();
			if(obj.equals("java02")){
//				li.add("java009");//添加元素
				li.set("java008");//删除元素
				li.remove();//修改元素
			}
		}
		System.out.println(al);
		//逆向遍历
		while (li.hasPrevious()) {
			System.out.println(li.previous());
		}
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void method(){
		ArrayList al=new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		System.out.println("原集合:"+al);
		//在指定位置添加元素
		al.add(1,"java09");
		//移除指定位置的元素
		al.remove(2);
		//修改指定位置上的元素
		al.set(0, "java001");
		//使用for循环遍历List集合
		for(int i=0;i<al.size();i++){
			System.out.println("al("+i+")="+al.get(0));
		}
		//使用迭代器遍历List集合
		for(Iterator it=al.iterator();it.hasNext();){
			System.out.println("next:"+it.next());
		}
		System.out.println(al);
		System.out.println("index="+al.indexOf("java03"));
		//截取List
		List sub=al.subList(0, 2);
		System.out.println(sub);
	}
}

LinkedList

LinkedList:底层使用的是链表数据结构;特点:增删点速度快,查询速度慢
LinkedList:特有方法
addFirst()
addLast()

getFirst()
getLast()
获取元素,但不删除元素,如果集合中没有元素,会出现NoSuchElementException
removeFirst()
removeLast()
获取元素,并删除元素,如果集合中没有元素,会出现NoSuchElementException
在jdk1.6出现了替代方法
offerFirst()
offerLast()

peekFirst()
peekLast()
获取元素,但不删除元素,如果集合中没有元素,会返回Null
poolFirst()
poolLast()
获取元素,并删除元素,如果集合中没有元素,会返回Null

Vector

Vector:底层是数组数据结构;线程同步,无论增删改查都慢,被ArrayList替代
        枚举就是Vector特有的取出方式。
        发现枚举和迭代器很像,其实枚举和迭代器是一样的。
        因为枚举的名称和方法的名称都过长。
        所以被迭代器取代了,枚举也就郁郁而终了
代码示例
public class VectorDemo {
	public static void main(String[] args) {
		Vector ve = new Vector();
		ve.add("java01");
		ve.add("java02");
		ve.add("java03");
		ve.add("java04");
		
		Enumeration en=ve.elements();
		while (en.hasMoreElements()) {
			System.out.println(en.nextElement());
		}
	}
}

Set集合

Set集合:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。Set集合的功能和Collection的功能是一致的

HashSet

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

                   HashSet是如何保证元素的唯一性呢?
                  是通过元素的两个方法,hashCode和equals来完成
                  如果元素hashcode值相同,才会判断equals是否为true
                  如果元素hashcode值不同,不会调用equals
                  注意:对于判断元素是否存在以及删除等操作,依赖的方法是元素的hashCode和equals方法,ArrayList 只依赖equals

代码示例
class Person {
	private String name;
	private int age;
	Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public int hashCode() {
		return name.hashCode() + age * 27;
	}
	public boolean equals(Object obj) {
		if (!(obj instanceof Person))
			return false;
		Person p = (Person) obj;
		System.out.println(this.name + "..." + p.name);
		return this.name.equals(p.name) && this.age == p.age;
	}
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
}
public class HashSetTest {
	public static void main(String[] args) {
		HashSet hs = new HashSet();
		hs.add(new Person("zhangsan01", 30));
		hs.add(new Person("zhangsan02", 32));
		hs.add(new Person("zhangsan03", 33));
		hs.add(new Person("zhangsan03", 33));
		hs.add(new Person("zhangsan04", 34));

		for (Iterator it = hs.iterator(); it.hasNext();) {
			Person per = (Person) it.next();
			System.out.println(per.getName() + "...." + per.getAge());
		}
	}
}
        只有类的实例对象要被采用哈希算法进行存储和检索时,这个类才需要按要求覆盖hashcode方法。即使程序可能暂时不会用到当前类的hashcode方法,但是为他提供一个hashcode方法也不会有什么不好,没准以后什么时候有用到这个方法了,所以通常要求hashcode方法和equals方法一并被同时覆盖
提示:
        (1)通常来说,一个类的两个实例对象用equals方法比较的结果相等时,他们的哈希码也必需相等,但反之则不成立,即equals方法比较的结果不相等可以有相同的哈希码,或者说哈希码相同的两个对象的equals方法比较结果可以不相等,例如,字符串“BB”和“Aa”的equals方法比较结果肯定不相等,但它们的hashcode方法返回值却相等。
        (2)当一个对象被存储进hashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进hashSet集合中的哈希值就不相同了,这中情况下在contains方法使用该对象的当前引用作为参数去hashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从hashSet集合中单独删除当前对象,从而造成内存泄漏

TreeSet

TreeSet:可以对集合中的元素进行排序
             底层数据结构是二叉树,存储的对象必需具备可比性不然会报ClassCastException异常。
             保证数据唯一性的依据是compareTo方法返回0
             TreeSet排序的第一种方式:让元素自身具备比较性 元素需要实现Comparable接口覆盖compareTo方法这种方式,也称为元素的自然顺序或者默认顺序
             TreeSet排序的第二种方式:当元素自身不具备比较性,或者具备的比较性不是锁需要的,这时,就需要集合自身具备比较性,让集合一初始化就有了比较方式
             方法:定义一个比较器,将比较器的对象作为参数传递给TreeSet集合的构造函数定义一个类实现Comparator接口,实现compare方法,
             两种比较方式都存在时,以比较器为主

代码示例
//实现Comparable接口让元素自身具备比较性
class Teacher implements Comparable{
	private String name;
	private int age;
	public Teacher(String name,int age) {
		this.name=name;
		this.age=age;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
	@Override
	public int compareTo(Object o) {
		if(!(o instanceof Teacher))
			throw new RuntimeException("不是教师对象");
		Teacher t=(Teacher)o;
		if(this.age>t.age)
			return 1;
		if(this.age==t.age){
			return this.name.compareTo(t.name);
		}
		return -1;
	}
}
public class TreeSetDemo {
	public static void main(String[] args) {
		//将比较器的对象作为参数传递给TreeSet集合的构造函数
			TreeSet ts=new TreeSet(new MyCompare());
			ts.add(new Teacher("lisi01", 22));
			ts.add(new Teacher("lisi03", 25));
			ts.add(new Teacher("lisi08", 24));
			ts.add(new Teacher("lisi06", 26));
			ts.add(new Teacher("lisi05", 26));
			ts.add(new Teacher("lisi07", 21));
			
			for (Iterator iterator = ts.iterator(); iterator.hasNext();) {
				Teacher t=(Teacher)iterator.next();
				System.out.println(t.getName()+"..."+t.getAge());
			}
	}
}
//定义一个比较器
class MyCompare implements Comparator {
	@Override
	public int compare(Object o1, Object o2) {
		Teacher t1 = (Teacher) o1;
		Teacher t2 = (Teacher) o2;
		int num = t1.getName().compareTo(t2.getName());
		if (num == 0) {
			return new Integer(t1.getAge()).compareTo(new Integer(t2.getAge()));
		}
		return num;
	}
}

三、Map集合

Map集合:该集合存储键值对,一对一对往里存,而且保证键的唯一性
主要方法
1、添加:
     V put(K key, V value) 
     void putAll(Map<? extends K,? extends V> m) 
2、删除
     void clear()  
     V remove(Object key) 
3、判断
     boolean containsKey(Object key) 
     boolean containsValue(Object value)  
     boolean isEmpty()  
4、获取
     V get(Object key) 
     int size()  
     Collection<V> values()  
     Set<Map.Entry<K,V>> entrySet() 
     Set<K> keySet() 

Hashtable

        底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的;jdk1.0,效率低

HashMap

        底层是哈希表数据结构,允许存入null键null值,该集合是不同步的;jdk1.2,效率高

TreeMap

        底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序
Map的两种取出方式
      Set<K> keySet():将map中所有的键存入到set集合。因为set集合具备迭代器
                       可以用迭代的方式去除所有的键,在根据get方法,获取每一个键对应的值
      Set<Map.Entry<K,V>> entrySet() 将映射关系存到Set集合中,再对Set集合进行遍历
示例代码
public class MapDemo2 {
	public static void main(String[] args) {
		HashMap<String, String> map = new HashMap<String, String>();
		map.put("01", "zhangsan1");
		map.put("02", "zhangsan2");
		map.put("03", "zhangsan3");
		map.put("04", "zhangsan4");

		// 第一种方式:先获取map集合中所有键的集合
		Set<String> keySet = map.keySet();
		Iterator<String> it = keySet.iterator();
		while (it.hasNext()) {
			String key = it.next();
			System.out.println(key + "==" + map.get(key));
		}
		// 第二种方式:将映射关系存到Set集合中,再对Set集合进行遍历
		Set<Map.Entry<String, String>> entrySet = map.entrySet();
		Iterator<Map.Entry<String, String>> it2 = entrySet.iterator();
		while (it2.hasNext()) {
			Map.Entry<String, String> entry = (Map.Entry<String, String>) it2.next();
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key + "==" + value);
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值