集合(下)


一、Set集合

1.Set集合概述
方法和List类似都继承于Collection类
1)特点:无序,唯一
2)子类:HashSet,TreeSet,LinkedHashSet等

2.HashSet集合
1)底层数据结构是哈希表(是一个元素为链表的数组),不保证 set 的迭代顺序;
2)哈希表底层依赖两个方法:hashCode()和equals()
 执行顺序:
首先比较哈希值是否相同
相同:继续执行equals()方法
返回true:元素重复了,不添加
返回false:直接把元素添加到集合
不同:就直接把元素添加到集合
3)HashSet 由hashCode()和equals()保证元素唯一性
4)对于hashCode()和equals(),开发的时候,自动生成即可。
5)LinkedHashSet
A:继承自HashSet,底层数据结构由哈希表和链表组成。
B:哈希表保证元素的唯一性。
6)  案例

HashSet存储自定义对象并遍历(对象的成员变量值相同即为同一个元素)

import java.util.HashSet;

/*
 * 需求:存储自定义对象,并保证元素的唯一性
 * 要求:如果两个对象的成员变量值都相同,则为同一个元素。
 * 
 * 目前是不符合我的要求的:因为我们知道HashSet底层依赖的是hashCode()和equals()方法。
 * 而这两个方法我们在学生类中没有重写,所以,默认使用的是Object类。
 * 这个时候,他们的哈希值是不会一样的,根本就不会继续判断,执行了添加操作。
 */
public class HashSetDemo {
	public static void main(String[] args) {
		// 创建集合对象
		HashSet<Student> hs = new HashSet<Student>();

		// 创建学生对象
		Student s1 = new Student("张三", 27);
		Student s2 = new Student("李四", 22);
		Student s3 = new Student("王五", 30);

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

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

class Student {
	private String name;
	private int age;

	public Student() {
		super();
	}

	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

}


4.TreeSet集合
1)底层数据结构是红黑树(是一个自平衡的二叉树)
2)保证元素的排序方式
A:自然排序(元素具备比较性), 让元素所属的类实现Comparable接口
B:比较器排序(集合具备比较性), 让集合构造方法接收Comparator的实现类对象

3)案例

import java.util.Comparator;
import java.util.TreeSet;

/*
 * 需求:请按照姓名的长度排序
 * 
 * TreeSet集合保证元素排序和唯一性的原理
 * 唯一性:是根据比较的返回是否是0来决定。
 * 排序:
 * 		A:自然排序(元素具备比较性)
 * 			让元素所属的类实现自然排序接口 Comparable
 * 		B:比较器排序(集合具备比较性)
 * 			让集合的构造方法接收一个比较器接口的子类对象 Comparator
 */
public class TreeSetDemo {
	public static void main(String[] args) {
		// 创建集合对象
		// TreeSet<Student> ts = new TreeSet<Student>(); //自然排序
		// public TreeSet(Comparator comparator) //比较器排序
		// TreeSet<Student> ts = new TreeSet<Student>(new MyComparator());

		// 如果一个方法的参数是接口,那么真正要的是接口的实现类的对象
		// 而匿名内部类就可以实现这个东西
		TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
			@Override
			public int compare(Student s1, Student s2) {
				// 姓名长度
				int num = s1.getName().length() - s2.getName().length();
				// 姓名内容
				int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
						: num;
				// 年龄
				int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
				return num3;
			}
		});

		// 创建元素
		Student s1 = new Student("linqingxia", 27);
		Student s2 = new Student("zhangguorong", 29);
		Student s3 = new Student("wanglihong", 23);
		Student s4 = new Student("linqingxia", 27);
		Student s5 = new Student("liushishi", 22);
		Student s6 = new Student("wuqilong", 40);
		Student s7 = new Student("fengqingy", 22);
		Student s8 = new Student("linqingxia", 29);

		// 添加元素
		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());
		}
	}
}


二、Map

1.Map的定义
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。 

2.Map和Collection的区别
A:Map 存储的是键值对形式的元素,键唯一,值可以重复。夫妻对
B:Collection 存储的是单独出现的元素,子接口Set元素唯一,子接口List元素可重复.

3.Map接口功能概述
1)添加功能:
V put(K key,V value):添加元素。这个其实还有另一个功能?先不告诉你,等会讲
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

2)删除功能:
void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回

3)判断功能:
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空

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

5)长度功能:
int size():返回集合中的键值对的对数

4.Map集合的遍历
1)键找值
A:获取所有键的集合
B:遍历键的集合,得到每一个键
C:根据键到集合中去找值

2)键值对对象找键和值
A:获取所有的键值对对象的集合
B:遍历键值对对象的集合,获取每一个键值对对象
C:根据键值对对象去获取键和值

代码体现:
		Map<String, String> hm = new HashMap<String, String>();

		hm.put("it002", "hello");
		hm.put("it003", "world");
		hm.put("it001", "java");

		// 方式1 键找值
		Set<String> set = hm.keySet();
		for (String key : set) {
			String value = hm.get(key);
			System.out.println(key + "---" + value);
		}

		// 方式2 键值对对象找键和值
		Set<Map.Entry<String, String>> set2 = hm.entrySet();
		for (Map.Entry<String, String> me : set2) {
			String key = me.getKey();
			String value = me.getValue();
			System.out.println(key + "---" + value);

5.案例
多层集合的嵌套遍历
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

public class HashMapDemo {
	public static void main(String[] args) {
		// 创建大集合
		HashMap<String, HashMap<String, ArrayList<Student>>> czbkMap = new HashMap<String, HashMap<String, ArrayList<Student>>>();

		// 一年级数据
		HashMap<String, ArrayList<Student>> bjCzbkMap = new HashMap<String, ArrayList<Student>>();
		ArrayList<Student> array1 = new ArrayList<Student>();
		Student s1 = new Student("张三", 27);
		Student s2 = new Student("李四", 30);
		array1.add(s1);
		array1.add(s2);
		ArrayList<Student> array2 = new ArrayList<Student>();
		Student s3 = new Student("丽丽", 28);
		Student s4 = new Student("高阁", 29);
		array2.add(s3);
		array2.add(s4);
		bjCzbkMap.put("1班", array1);
		bjCzbkMap.put("2班", array2);
		czbkMap.put("一年级", bjCzbkMap);


		// 二年级数据
		HashMap<String, ArrayList<Student>> xaCzbkMap = new HashMap<String, ArrayList<Student>>();
		ArrayList<Student> array3 = new ArrayList<Student>();
		Student s5 = new Student("小赵", 27);
		Student s6 = new Student("小钱", 30);
		array3.add(s5);
		array3.add(s6);
		ArrayList<Student> array4 = new ArrayList<Student>();
		Student s7 = new Student("小孙", 28);
		Student s8 = new Student("小李", 29);
		array4.add(s7);
		array4.add(s8);
		xaCzbkMap.put("1班", array3);
		xaCzbkMap.put("2班", array4);
		czbkMap.put("二年级", xaCzbkMap);

		// 遍历集合
		Set<String> czbkMapSet = czbkMap.keySet();
		for (String czbkMapKey : czbkMapSet) {
			System.out.println(czbkMapKey);
			HashMap<String, ArrayList<Student>> czbkMapValue = czbkMap
					.get(czbkMapKey);
			Set<String> czbkMapValueSet = czbkMapValue.keySet();
			for (String czbkMapValueKey : czbkMapValueSet) {
				System.out.println("\t" + czbkMapValueKey);
				ArrayList<Student> czbkMapValueValue = czbkMapValue
						.get(czbkMapValueKey);
				for (Student s : czbkMapValueValue) {
					System.out.println("\t\t" + s.getName() + "---"
							+ s.getAge());
				}
			}
		}
	}
}


三、Collections

1.是针对集合进行操作的工具类

2.Collection和Collections的区别
1)Collection 是单列集合的顶层接口,有两个子接口List和Set
2)Collections 是针对集合进行操作的工具类,可以对集合进行排序和查找等

3.常见的几个小方法:
1)public static <T> void sort(List<T> list):排序 默认情况下是自然顺序。
2)public static <T> int binarySearch(List<?> list,T key):二分查找
3)public static <T> T max(Collection<?> coll):最大值
4)public static void reverse(List<?> list):反转
5)public static void shuffle(List<?> list):随机置换

4.案例

模拟斗地主洗牌和发牌并对牌进行排序

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

/*
 * 思路:
 * 		A:创建一个HashMap集合
 * 		B:创建一个ArrayList集合
 * 		C:创建花色数组和点数数组
 * 		D:从0开始往HashMap里面存储编号,并存储对应的牌
 *        同时往ArrayList里面存储编号即可。
 *      E:洗牌(洗的是编号)
 *      F:发牌(发的也是编号,为了保证编号是排序的,就创建TreeSet集合接收)
 *      G:看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)
 */
public class PokerDemo {
	public static void main(String[] args) {
		// 创建一个HashMap集合
		HashMap<Integer, String> hm = new HashMap<Integer, String>();

		// 创建一个ArrayList集合
		ArrayList<Integer> array = new ArrayList<Integer>();

		// 创建花色数组和点数数组
		// 定义一个花色数组
		String[] colors = { "♠", "♥", "♣", "♦" };
		// 定义一个点数数组
		String[] numbers = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q",
				"K", "A", "2", };

		// 从0开始往HashMap里面存储编号,并存储对应的牌,同时往ArrayList里面存储编号即可。
		int index = 0;

		for (String number : numbers) {
			for (String color : colors) {
				String poker = color.concat(number);
				hm.put(index, poker);
				array.add(index);
				index++;
			}
		}
		hm.put(index, "小王");
		array.add(index);
		index++;
		hm.put(index, "大王");
		array.add(index);

		// 洗牌(洗的是编号)
		Collections.shuffle(array);

		// 发牌(发的也是编号,为了保证编号是排序的,就创建TreeSet集合接收)
		TreeSet<Integer> fengQingYang = new TreeSet<Integer>();
		TreeSet<Integer> linQingXia = new TreeSet<Integer>();
		TreeSet<Integer> liuYi = new TreeSet<Integer>();
		TreeSet<Integer> diPai = new TreeSet<Integer>();

		for (int x = 0; x < array.size(); x++) {
			if (x >= array.size() - 3) {
				diPai.add(array.get(x));
			} else if (x % 3 == 0) {
				fengQingYang.add(array.get(x));
			} else if (x % 3 == 1) {
				linQingXia.add(array.get(x));
			} else if (x % 3 == 2) {
				liuYi.add(array.get(x));
			}
		}

		// 看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)
		lookPoker("风清扬", fengQingYang, hm);
		lookPoker("林青霞", linQingXia, hm);
		lookPoker("刘意", liuYi, hm);
		lookPoker("底牌", diPai, hm);
	}

	// 写看牌的功能
	public static void lookPoker(String name, TreeSet<Integer> ts,
			HashMap<Integer, String> hm) {
		System.out.print(name + "的牌是:");
		for (Integer key : ts) {
			String value = hm.get(key);
			System.out.print(value + " ");
		}
		System.out.println();
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值