黑马程序员--集合

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------


集合是用来存储和管理其他对象的对象,即对象的容器。

集合的特点:集合只用于存储对象,集合的长度是可变的,可以存储不同类型的对象。集合中存储的都是对象的引用 (地址)。


集合框架图

从集合框架图中可以看出,java的集合类主要由两个接口派生而出:collection和Map,Collection和Map是java集合框架的跟接口,这两个接口又包含了一些子接口或实现类。


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

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


List接口提供了特殊的迭代器,称为 ListIterator,除了允许 Iterator 接口提供的正常操作外,该迭代器还允许元素插入和替换,以及双向访问。还提供了一个方法来获取从列表中指定位置开始的列表迭代器。


注:在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。所以在迭代时,只能用迭代器的方法操作元素。可是Iterator方法是有限的,只能对元素进行判断、取出、删除操作。如果想要其他操作,如添加,修改等,就要使用其接口ListIterator。该接口只能通过List集合的ListIterator获取。


List集合的主要实现类:

ArrayList:底层的数据结构使用的是数组结构。特点:查询速度快,但是增删较慢,线程不同步。

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

Vector:底层使用的是数组数据结构。线程同步,被ArrayList替代了。

List集合判断元素是否相同,依据的是元素的equals方法。


例子:List集合的常见操作

import java.util.*;
class CollectDemo
{
	public static void main(String[] args)
	{
		//method_2();
		method_get();
	}
	
	public static void method_get()
	{
		ArrayList al = new ArrayList();
		
		al.add("java01");//add(Object obj)
		al.add("java02");
		al.add("java05");
		al.add("java08");
		
		Iterator it = al.iterator();//获取迭代器,用于去除集合中的元素
		while(it.hasNext())
		{
			sop(it.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("java07");
		al1.retainAll(al2);//取交集
		//al1.removeAll(al2);//去除交集
		
		sop("al1:"+al1);
		sop("al2:"+al2);
	}
	
	public static void method_1()
	{
		//创建一个集合容器。使用collection接口
		ArrayList al = new ArrayList();
		//1.添加元素
		al.add("java01");//add(Object obj)
		al.add("java02");
		al.add("java03");
		al.add("java04");
		
		//2.获取个数,集合长度
		sop("size:"+al.size());
		//打印原集合
		sop("原集合:"+al);
		//3.删除集合元素
		al.remove(2);
		//4.判断元素
		sop("java02是否存在?"+al.contains("java02"));
		
		sop("集合是否为空?"+al.isEmpty());
		//清空集合
		//al.clear();
		
		sop("size:"+al.size());
		
		sop("改变后的集合:"+al);
		
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}




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


Set集合的主要实现类:

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

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


TreeSet如何实现排序?

(1)第一种方式:让元素自身具备比较性,元素需要实现Compareble接口,覆盖compareTo方法。这种方式也称为元素的自然顺序,也称作默认排序。

(2)第二种方式:当元素自身不具有比较性时,或者具备的比较性不是所需的,这时需要让自身具备比较性,在集合初始化时就让其具有比较方式。


HashSet是如何保证元素唯一性的?

是通过元素的两个方法:hashCode和equals来完成。如果元素的hashCode值相同,才会判断equals是否为true,如果元素的hashCode值不同,不会调用equals。

注:排序时,当主要条件相同时,一定要判断次要条件是否相同。


例子:TreeSet排序

/*
按照字符串长度排序。
字符串本身具有比较性。但是它的比较方式不是所需要的。
这时就只能使用比较器。
*/

import java.util.*;
class TreeSetTest
{
	public static void main(String[] args)
	{
		TreeSet ts = new TreeSet(new StrLenComparator());
		
		ts.add("abcd");
		ts.add("cc");
		ts.add("cba");
		ts.add("z");
		ts.add("hahaha");
		ts.add("bbb");
		Iterator it = ts.iterator();
		
		while(it.hasNext())
		{
			
			System.out.println(it.next());
		}
	}
}

class StrLenComparator implements Comparator
{
	public int compare(Object obj1,Object obj2)
	{
		String s1=(String)obj1;
		String s2=(String)obj2;
		
		int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
		if(num==0)
			return s1.compareTo(s2);
		return num;
		
		
	}
}


泛型:用于解决安全问题,是一个类安全机制。

好处:(1)将运行时期出现的问题ClassCastException,转移到了编译时期,方便于程序员解决问题,让运行时问题 减少,安全。

 (2)避免了强制转换的麻烦。

格式:通过<>来定义要操作的引用数据类型。

什么时候定义泛型呢?

通常在集合框架中很常见,只要见到<>,就要定义泛型。使用集合时,将集合中要存储的数据类型作为参数传递到<>即可。

泛型类:当类中要操作的引用数据类型不确定时,早期定义Object来完成扩展,现在定义泛型类来完成。

泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛类型的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。静态方法不可以访问类上定义的泛型,如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。


符号解释:

?:是通配符,也可理解为占位符。

?extends E:可以接收E类型或者E的子类型。上限限定。

?super E:可以接收E类型或者E的父类型。下限限定。


Map集合:该集合存储键值对。一对一对往里存,而且要保证键的唯一性。

Map集合的主要实现类:

Hashtable:底层是哈希数据结构,不可以存入null值或null键,该集合是线程同步。

HashMap:底层是哈希数据结构,允许存入null值或null键,该集合是线程不同步,效率高。

TreeMap:底层是二叉树结构,线程不同步。可以用于给Map集合中的键进行排序。


Map集合的取出原理:将Map集合转成Set集合,再通过迭代器取出。


例子:

/*
map集合的两种取出方式
*/
import java.util.*;
class MapDemo
{
	public static void main(String[] args)
	{
		Map<String,String> map = new HashMap<String,String>();
		
		map.put("02","zhangsan2");
		map.put("04","zhangsan4");
		map.put("01","zhangsan1");
		map.put("03","zhangsan3");
		//第二种取出方式
		//将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();
		//获取其迭代器
		Iterator<String> it = keySet.iterator();
		
		while(it.hasNext())
		{
			String key = it.next();
			//有了键就可以通过map集合的get方法获取其对应的值
			String value = map.get(key);
			System.out.println("key:"+key+","+"value:"+value);
		}*/
	}
}

例子:"sdfgzxcvasdfxcvdf"获取该字符串中字母出现的次数。
希望打印结果:a(1)c(2)......

分析:通过结果发现,每一个字母都有对应的次数。说明字母和次数之间都有映射关系,
所以可以选择map集合。

思路:1.将字符串转换成字符数组,因为要对每一个字母进行操作。
2.定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合
3.遍历字符数组。
将每一个字母作为键去查map集合,如果返回null,将该字母和1存入到map集合中。
如果返回不为null,说明该字母在map集合中已经存在并有对应次数,那么就获取该次数并进行自增。然 后将该字母和自增后的次数存到map集合中。覆盖原有键所对应的值。
4.将map集合中的数据变成指定的字符串形式返回。

import java.util.*;

class MapText2
{
	public static void main(String[] args)
	{
		String s = "sdfgzxcvasdfxcvdf";
		System.out.println(s);
		s=charCount(s);
		System.out.println(s);
	}
	
	public static String charCount(String str)
	{
		char[] chs = str.toCharArray();
		TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
		for(int x=0;x<chs.length;x++)
		{
			Integer value = tm.get(chs[x]);
			if(value == null)
			{
				tm.put(chs[x],1);
			}
			else 
			{
				value ++;
				tm.put(chs[x],value);
			}	
		}
		//System.out.println(tm);
		
		StringBuilder sb = new StringBuilder();
		Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
		Iterator <Map.Entry<Character,Integer>> it = entrySet.iterator();
		
		while(it.hasNext())
		{
			Map.Entry<Character,Integer> me = it.next();
			Character ch = me.getKey();
			Integer value = me.getValue();
			sb.append(ch+"("+value+")");
		}
		return sb.toString();
	}
}



-------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值