黑马程序员--java学习之集合框架

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


一.集合框架概述

集合框架就是容器,用来装对象,各种容器中对数据的处理存储方式有所不同。即数据结构不同,集合框架支持3种类型的集合:规则集(Set),线性表(List),和图(Map,分别定义在SetListMap中。Set实例存储一组互不相同的元素(集合),List实例存储一组顺序排列的元素(表),Map存储一组对象---关键值的映射:

总的架构如下,非常重要,包含继承关系,实现的分类,一目了然:

Collection
接口: 

Set接口:元素是无序,元素不可以重复。

HashSet底层数据结构是哈希表。是线程不安全的。不同步。HashSet是如何保证元素唯一性的呢?是通过元素的两个方法,hashCodeequals来完成。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals。这个equals方法是覆盖Object的,而Object不带泛型,所以在equals方法中必须强制转换类型,注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcodeequals方法。

TreeSet可以对Set集合中的元素进行排序,线程非同步。底层数据结构是二叉树,保证元素唯一性的依据:compareTo方法

 

List接口:实现表、列、堆的数据结构            

ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步,多线程应用时需要锁,初始容量为10个对象元素,超过的话每次自增50%
  LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
  Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低,集合框架存在之前就已经有了

 

Map接口:
   HashMap:底层是哈希表数据结构,允许使用 null 值和 null键,该集合是不同步的。    hashtable替代,从jdk1.2开始有此集合,.效率高。
     TreeMap
:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。 

Hashtable:底层是哈希表数据结构,不可以存入nullnull值。该集合是线程同步的,.效率低。

 

SetList比:
Set
索元素效率低下,除和入效率高,入和除不引起元素位置改无序,所存象唯一,不可以重存放。
List
:和数组类似,List可以动态找元素效率高,除元素效率低,因为会引起其他元素位置改有序可以重存放    

 

一.Collection接口的共性方法:

1,添加

      boolean add(e);

      boolean addAll(collection);

 

2,删除

      boolean  remove(e);

      boolean  removeAll(collection);

      void clear();

 

3,判断。

      contains(e);

      isEmpty();

 

4,获取

      iterator();

      size();

 

5,获取交集。

      retainAll();

 

6,集合变数组。

      toArray();

三.有关迭代器的知识点:

其实就是集合的取出元素的方式。各种集合容器的数据结构不同,所以取出数据

的动作也不同,但都有共性的需要就是判断取出,在容器内部专门定义了内部类用以

实现这些共性的需要,这些内部类都符合一个规则,该规则就是Iterator接口,通过此接

口对外提供的方法iterator()即可实现需要,此即为迭代,就如同抓娃娃游戏机中的夹子。迭代器是取出方式,会直接访问集合中的元素,所以将迭代器通过内部类的形式来进行描述。

通过容器的iterator()方法获取该内部类的对象。ListIteratorIterator的子接口。在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以,在迭代器时,只能用迭代器的放过操作元素,可是Iterator方法是有限的,

只能对元素进行判断,取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。该接口只能通过List集合的listIterator方法获取。

示例代码:

import java.util.*;
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);
ListIterator li = al.listIterator();
		while(li.hasNext())
		{
			Object obj = li.next();

			if(obj.equals("java02"))
				li.set("java006");
		}
		//在迭代过程中,准备添加或者删除元素。

		Iterator it = al.iterator();

		while(it.hasNext())
		{
			Object obj = it.next();

			if(obj.equals("java02"))
				it.remove();//将java02的引用从集合中删除了
			sop("obj="+obj);
		}
		sop(al);
	}
}

四.LinkedList

特有方法有addFirst();addLast();getFirst();getLast();这些方法获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException,在JDK1.6出现了替代方法,包括offerFirst();offerLast();peekFirst();peekLast();

小练习:使用LinkedList模拟一个堆栈或者队列数据结构。

import java.util.*;
class DuiLie
{
	private LinkedList link;

	DuiLie()
	{
		link = new LinkedList();
	}
	
	public void myAdd(Object obj)
	{
		link.addFirst(obj);//添加数据总是添加在第一个角标位置上
	}
	public Object myGet()
	{
		return link.removeFirst();//删除数据也总是删除第一个位置
	}
	public boolean isNull()
	{
		return link.isEmpty();
	}
}

class  LinkedListTest
{
	public static void main(String[] args) 
	{
		DuiLie dl = new DuiLie();
		dl.myAdd("java01");
		dl.myAdd("java02");
		dl.myAdd("java03");
		dl.myAdd("java04");

		while(!dl.isNull())
		{
			System.out.println(dl.myGet());
		}
	}
}


五.HashSet

      示例

import java.util.*;
/*
往hashSet集合中存入自定对象
姓名和年龄相同为同一个人,重复元素。
*/
class HashSetTest 
{
	public static void sop(Object obj)
	{
		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.add(new Person("a4",14));	
		hs.remove(new Person("a4",13));

		Iterator it = hs.iterator();
		while(it.hasNext())
		{
			Person p = (Person)it.next();
			sop(p.getName()+"::"+p.getAge());
		}
	}
}
class Person
{
	private String name;
	private int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	
	public int hashCode()//底层会先调用此方法进行判断两个对象元素的Hashcode是否一样
	{
		System.out.println(this.name+"....hashCode");
		return name.hashCode()+age*37;
	}

	public boolean equals(Object obj)  //若加入hashset的元素的哈希值相同,则hashaset底层会自动调用此方法
	{

		if(!(obj instanceof Person))
			return false;

		Person p = (Person)obj;
		System.out.println(this.name+"...equals.."+p.name);

		return this.name.equals(p.name) && this.age == p.age;
	}

	
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}

六:TreeSet

可以对Set集合中的元素进行排序,TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也成为元素的自然顺序,或者叫做默认顺序。

示例代码:

class TreeSetDemo 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet();

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi08",19));
		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 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;
	}
}

第二种方式:让元素类实现Comparator接口,并覆盖compare方法。当元素自身不具备比较性,或者具备的比较性不是所需要的。这时需要让容器自身具备比较性。定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

 

示例代码:

class TreeSetDemo2 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet();

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi02",21));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi06",18));
		ts.add(new Student("lisi06",18));
		ts.add(new Student("lisi007",29));
		//ts.add(new Student("lisi007",20));
		//ts.add(new Student("lisi01",40));

		Iterator it = ts.iterator();
		while(it.hasNext())
		{
			Student stu = (Student)it.next();
			System.out.println(stu.getName()+"..."+stu.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;
	}
}

七.Map集合

map集合的两种取出方式:

1Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。

 

2Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry,set集合中存储的都是Map.Entry的实例对象,Map.Entry其实就是Map中的一个static内部接口。为什么要定义在内部呢?因为只有有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。而且该事物在直接访问Map集合中的元素。

 

3.HashMapTreeMap应用详解

      HashSet应用的示例代码:

import java.util.*;
class MapDemo2 
{
	public static void main(String[] args) 
	{
		Map<String,String> map = new HashMap<String,String>();
		map.put("02","zhangsan2");
		map.put("03","zhangsan3");
		map.put("01","zhangsan1");
		map.put("04","zhangsan4");

		//将Map集合中的映射关系取出。存入到Set集合中,这是第二种取出方式
		Set<Map.Entry<String,String>> entrySet = map.entrySet();
		Iterator<Map.Entry<String,String>> it = entrySet.iterator();
/*第一种取出方式的写法:
		//先获取map集合的所有键的Set集合,keySet();
		Set<String> keySet = map.keySet();
		//有了Set集合。就可以获取其迭代器。
		Iterator<String> it = keySet.iterator();

*/
		while(it.hasNext())
		{
			Map.Entry<String,String> me = it.next();
			String key = me.getKey();
			String value = me.getValue();

			System.out.println(key+":"+value);

		}
	}
}

TreeMap在应用时,多了排序的功能,而且它是根据键的元素排序的,相应的,健的元素需要实现Comparable或者Comparator接口,具体与TreeSet类似。

      示例代码:

/*
需求:对学生对象的年龄进行升序排序。

因为数据是以键值对形式存在的。
所以要使用可以排序的Map集合。TreeMap。
*/
import java.util.*;

class StuNameComparator implements Comparator<Student>
{
	public int compare(Student s1,Student s2)
	{
		int num = s1.getName().compareTo(s2.getName());
		if(num==0)
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));

		return num;
	}
}


class  MapTest2
{
	public static void main(String[] args) 
	{
		TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameComparator());

		tm.put(new Student("blisi3",23),"nanjing");
		tm.put(new Student("lisi1",21),"beijing");
		tm.put(new Student("alisi4",24),"wuhan");
		tm.put(new Student("lisi1",21),"tianjin");
		tm.put(new Student("lisi2",22),"shanghai");
		Set<Map.Entry<Student,String>> entrySet = tm.entrySet();
		Iterator<Map.Entry<Student,String>> it = entrySet.iterator();
		while(it.hasNext())
		{
			Map.Entry<Student,String> me = it.next();
			Student stu = me.getKey();
			String addr = me.getValue();
			System.out.println(stu+":::"+addr);
		}
	}
}


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值