黑马程序员 集合框架二

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

集合框架二

1:Set
(1)Set的特点:
元素无序,唯一。
注意:这里的顺序是指存储和取出顺序。


2:HashSet
(1)HashSet:不保证元素的迭代顺序。并且,不保证该顺序恒久不变。
(2)怎么保证的呢?
HashSet底层数据结构是哈希表。
它依赖两个方法:hashCode()和equals()
顺序:
首先,判断hashCode()值是否相同。
相同:
继续走equals()方法,根据其返回值:
true:说明元素重复,不添加到集合。
false:说明元素不重复,添加到集合。
不同:直接添加到集合。
(3)怎么重写hashCode()和equals()方法呢?
hashCode():
把对象的所有成员变量值相加即可。
如果是基本类型,就加值。如果是引用类型,就加哈希值。
equals():
A:this==obj
B:!(obj instanceof Student)
C:所有成员变量的值比较。基本类型用==,引用类型用equals()。


如果不会,可以自动生成。
(4)案例:
HashSet存储字符串并遍历

/*
 * HashSet存储字符串并遍历
 */
public class HashSetDemo {
	public static void main(String[] args) {
		// 创建集合对象
		HashSet<String> hs = new HashSet<String>();

		// 创建并添加元素
		hs.add("hello");
		hs.add("world");
		hs.add("java");
		hs.add("java");

		// 遍历
		for (String s : hs) {
			System.out.println(s);
		}
	}
}


HashSet存储自定义对象并遍历

/*
 * HashSet存储自定义对象。
 * 需求:我们认为一个对象如果成员变量值都相同,则为同一个对象。
 * 
 * 请思考:
 * 		A:哪里出问题了
 * 			通过简单的分析,我们知道了在add方法出问题了。
 * 		B:怎么解决
 * 			看源码
 * 通过看源码:我们知道,最终的操作跟如下这个判断相关
 * 		if(e.hash == hash && ((k = e.key) == key || key.equals(k)))
 * 		{
 * 			唯一。
 * 		}
 * 分析条件:
 * 		A:这个判断跟对象的hashCode()方法相关。
 * 		B:这个判断跟equals()方法相关。
 * 
 * 
 * 总结:
 * 		HashSet如何保证元素的唯一性的呢?
 * 			HashSet的底层数据结构是哈希表。
 * 			它依赖两个方法,hashCode()和equals()。
 * 			顺序:
 * 				首先,判断对象的hashCode()值是否相同。
 * 					相同:
 * 						继续走equals()。看返回值是true还是false
 * 							A:如果是true,说明有元素重复。该元素不添加到集合。
 * 							B:如果是false,说明元素不重复,该元素添加到集合。
 * 					不同:就直接添加到集合中了。
 */
public class HashSetDemo2 {
	public static void main(String[] args) {
		// 创建集合对象
		HashSet<Student> hs = new HashSet<Student>();

		// 创建元素对象
		Student s1 = new Student("周霞", 26);
		Student s2 = new Student("王玉", 36);
		Student s3 = new Student("张敏", 20);
		Student s4 = new Student("周霞", 26);
		Student s5 = new Student("周霞", 66);
		Student s6 = new Student("李玲", 16);

		// 添加元素
		hs.add(s1);
		// hs.add(s1);
		hs.add(s2);
		hs.add(s3);
		hs.add(s4);
		hs.add(s5);
		hs.add(s6);

		// 遍历
		for (Student s : hs) {
			System.out.println(s.getName() + "***" + s.getAge());
		}
	}
}


针对自定义对象:
需求:如果对象的成员都相同,我们就认为是同一个元素。


3:TreeSet
(1)TreeSet:根据构造方法的不用,选择使用自然排序或者比较器排序。
           按照实际的需求,可以对元素进行排序。并且保证唯一。
(2)怎么保证的呢?
排序:底层结构是二叉树。按照树节点进行存储和取出。
两种实现:
A:自然排序(元素具备比较性)
TreeSet的无参构造,要求对象所属的类实现Comparable接口。
B:比较器排序(集合具备比较性)
TreeSet的带参构造,要求构造方法接收一个实现了Comparator接口的对象。
唯一:根据返回值是否为0。

注意:
如果同时有两种方案,以谁为主呢?以比较器为主。
(3)案例:
TreeSet存储字符串并遍历

/*
 * TreeSet可以对元素进行排序。
 * 使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。 
 */
public class TreeSetDemo {
	public static void main(String[] args) {
		// 创建集合对象
		TreeSet<String> ts = new TreeSet<String>();

		// 创建并添加元素
		ts.add("hello");
		ts.add("world");
		ts.add("java");
		ts.add("abcde");
		ts.add("zone");
		// ts.add("world");

		// 遍历
		for (String str : ts) {
			System.out.println(str);
		}
	}
}


TreeSet存储Integer并遍历

/*
 * TreeSet存储Integer类型的数据,保证唯一和排序
 */
public class TreeSetTest {
	public static void main(String[] args) {
		// 20,18,23,22,17,24,19,18,24
		TreeSet<Integer> ts = new TreeSet<Integer>();

		// 添加元素
		ts.add(20);
		ts.add(18);
		ts.add(23);
		ts.add(22);
		ts.add(17);
		ts.add(24);
		ts.add(19);
		ts.add(18);
		ts.add(24);

		// 遍历
		for (Integer i : ts) {
			System.out.println(i);
		}
	}
}


TreeSet存储自定义对象并遍历
/*
 * TreeSet存储自定义对象。
 * 保证元素有序和唯一。
 * 
 * Exception in thread "main" java.lang.ClassCastException: 
 * cn.itcast_03.Student cannot be cast to java.lang.Comparable
 * 
 * TreeSet保证元素排序有两种方式:
 * A:自然顺序 让对象所属的类去实现Comparable接口。无参构造。
 * B:比较器接口 Comparator。带参构造。
 * 
 * 在自然排序中,又是如何保证排序的呢?
 * 根据返回值看:
 * 		正	就说明元素比以前的元素大,往后放。
 * 		负	就说明元素比以前的元素小,往前放。
 * 		0	元素就不添加到集合中。着就是保证唯一性的原理。
 * 
 * 需求:我想按照对象的年龄排序,从小到大排序。怎么做?
 * 
 * 需求:我想按照姓名的长度排序,从小到大排序。怎么做?
 */
public class TreeSetDemo2 {
	public static void main(String[] args) {
		// 创建集合对象
		TreeSet<Student> ts = new TreeSet<Student>();

		// 创建元素对象
		Student s1 = new Student("liudehua", 52);
		Student s2 = new Student("chenglong", 60);
		Student s3 = new Student("zhouxinchi", 44);
		Student s4 = new Student("sunyanzi", 34);
		Student s5 = new Student("linqingxia", 26);
		Student s6 = new Student("linqingxia", 36);
		Student s7 = new Student("linqing", 26);
		Student s8 = new Student("linqingxia", 26);

		// 添加元素
		ts.add(s1);
		ts.add(s2);
		ts.add(s3);
		ts.add(s4);
		ts.add(s5);
		ts.add(s6);
		ts.add(s7);
		ts.add(s8);

		// 遍历
		for (Student s : ts) {
			System.out.println(s.getName() + "***" + s.getAge());
		}
	}
}




4:Collection体现的集合总结
Collection
|--List
|--ArrayList
底层数据结构是数组,查询快,增删慢
线程不安全,效率高。
|--LinkedList
底层数据结构是链表,查询慢,增删快
线程不安全,效率高。
|--Vector
底层数据结构是数组,查询快,增删慢
线程安全,效率低。
|--Set 唯一
|--HashSet
底层数据结构是哈希表。
如何保证元素唯一性呢?
依赖两个方法。hashCode()和equals()。
以后都自动生成。
|--TreeSet
底层数据结构是二叉树。
如何保证元素唯一性呢?如何保证元素排序呢?
根据返回值是否是0,判断元素是否重复。
排序有两种方案:
元素具备比较性 实现Comparable接口
集合具备比较性 实现Comparator接口


5:在集合中的数据结构问题
ArrayXxx:底层数据结构是数组。查询快,增删慢。
LinkedXxx:底层数据结构是链表。查询慢,增删快。
HashXxx:底层数据结构是哈希表。跟两个有关。hashCode()和equals()
TreeXxx:底层数据结构是二叉树。两种排序方式。Comparable接口和Comparator接口


6:什么时候,使用哪种Collection集合。
元素唯一吗?
唯一:
Set
需要排序吗?
需要:TreeSet
不需要:HashSet


不知道,用HashSet。
不唯一:
List
需要安全码?
需要:Vector
不需要:ArrayList和LinkedList
查询多:ArrayList
增删多;LinkedList
不知道,用ArrayList。


7:Collections
(1)Collections是针对Collection集合操作的工具类。
(2)面试题:
Collection和Collections的区别?

Collection:是Collection集合的顶层接口,定义了Collection集合的共性方法。
Collections:是一个类,定义了针对Collection集合操作的功能。有排序,查找,反转等。

(3)功能:
排序public static void sort(List list)
查找public static <T> int binarySearch(List list,T key)
反转public static void reverse(List list)
最值public static  T max(Collection coll)
随机置换public static void shuffle(List list)


8:Map
(1)Map是一个键值对形式的集合。它的元素都是有键和值组成。
(2)Map和Collection的区别?(面试题)
A:Map 是由键值对组成的集合,Map的键是唯一的,值可以重复。
B:Collection 是有单列数据组成的集合,它的儿子List是可以重复的,Set是唯一的。
(3)HashMap和Hashtable的区别?(面试题)
HashMap:线程不安全,效率高。允许null键和值。
Hashtable:线程安全,效率低。不允许null键和值。
(4)Map的功能:(自己补齐)
A:添加功能
V put(K key,V value):当key在集合中不存在时,添加元素,当Key在集合中存在时,替换元素。

B:判断功能
boolean containsKey(Object key):判断指定的键是否在集合中存在
boolean containsValue(Object value):判断指定的值是否在集合中存在
boolean isEmpty():判断集合是否为空


C:删除功能
void clear():清除所有键值对数据
V remove(Object key):根据指定的键删除键值对。


D:获取功能
Set<Map.Entry<K,V>> entrySet():键值对对象的集合
Object get(Object key):根据键获取值
Set<K> keySet():所有键的集合
Collection<V> values():所有值的集合


E:长度功能
int size()


(5)Map的两种遍历方式
A:丈夫找妻子
a:把所有丈夫给集中起来。Set<K> keySet()
b:遍历丈夫集合,获取到每一个丈夫。迭代器,增强for
c:让丈夫去找妻子。get(Object key)

代码实现:
A:丈夫找妻子

/*
 * Object get(Object key):根据键获取值
 * Map集合的遍历。
 * 		方式1:丈夫找妻子
 * 			A:把所有丈夫给集中起来。Set<K> keySet()
 * 			B:遍历丈夫集合,获取到每一个丈夫。迭代器,增强for
 * 			C:让丈夫去找妻子。get(Object key)
 */
public class MapDemo3 {
	public static void main(String[] args) {
		// 创建集合对象
		Map<String, String> map = new HashMap<String, String>();

		// 创建并添加元素
		map.put("杨过", "小龙女");
		map.put("郭靖", "黄蓉");
		map.put("梁山伯", "祝英台");
		map.put("牛郎", "织女");

		// 键的集合
		Set<String> set = map.keySet();
		for (String str : set) {
			System.out.println(str);
		}
		System.out.println("---------");
		// 值的集合
		Collection<String> con = map.values();
		for (String str : con) {
			System.out.println(str);
		}
		System.out.println("---------");
		// 根据键获取值
		// Object get(Object key):根据键获取值
		System.out.println(map.get("郭靖"));
		System.out.println(map.get("牛郎"));
		System.out.println(map.get("田野"));
		System.out.println("---------");
		// 遍历
		// A:把所有丈夫给集中起来。Set<K> keySet()
		Set<String> husbandSet = map.keySet();
		// B:遍历丈夫集合,获取到每一个丈夫。迭代器,增强for
		for (String husband : husbandSet) {
			// C:让丈夫去找妻子。get(Object key)
			String wife = map.get(husband);
			System.out.println(husband + "***" + wife);
		}
	}
}


B:根据结婚证找丈夫和妻子

/*
 * Map集合的遍历。
 * 方式2:通过结婚证找丈夫和妻子。
 * 		A:获取所有结婚证的集合。Set<结婚证> entrySet()
 * 			class 结婚证<K,V>
 * 			{
 * 				private K key;
 * 				private V value;
 * 
 * 				public 结婚证(K key,V value)
 * 				{
 * 					this.key = key;
 * 					this.value = value;
 * 				}
 * 
 * 				public K getKey()
 * 				{
 * 					return key;
 * 				}
 * 
 * 				public V getValue()
 * 				{
 * 					return value;
 * 				}
 * 			}
 * 		B:遍历结婚证集合,获取到每一个结婚证对象。迭代器,增强for。
 * 		C:通过结婚证对象获取丈夫和妻子。
 */
public class MapDemo4 {
	public static void main(String[] args) {
		// 创建集合对象
		Map<String, String> map = new HashMap<String, String>();

		// 创建并添加元素
		map.put("杨过", "小龙女");
		map.put("郭靖", "黄蓉");
		map.put("梁山伯", "祝英台");
		map.put("牛郎", "织女");

		// 获取结婚证的集合
		// Set<Map.Entry<K,V>> entrySet():键值对对象的集合。
		Set<Map.Entry<String, String>> set = map.entrySet();
		// 遍历结婚证集合,获取到每一个结婚证对象
		for (Map.Entry<String, String> me : set) {
			// 通过结婚证对象获取丈夫和妻子。
			String key = me.getKey();
			String value = me.getValue();
			System.out.println(key + "***" + value);
		}
	}
}


---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值