一、Set集合
 1、什么是Set集合?
  Set是Collection的一种,即Set是Collection的子接口。
 2、Set有什么特性:
  1.它不要求顺序,无重复元素
  2.没索引
 3、Set有五种实现类:
  1.HashSet 2.TreeSet 3.LinkedHashSet 
 4、HashSet TreeSet LinkedHashSet它们分别有什么特征?
      HashSet特征:
 1.它的底层是用hash表数据结构,线程不同步,无序,高效。
 2.HashSet集合保证了元素的唯一性:通过元素的HasCode方法和equals方法完成的。
 3.当元素的HashCode值相同时,才继续判断元素的equals值是否是否为true。如果为true,那么视为相同元素,不存储。如果为false,那么存储。
 4.如果HashCode不同,那么不比较equas方法,直接存储,从而直接提高对象比较的速度。
 HashCode实例:

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class ComparableDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		创建一个Set集合的引用指向HashSet的对象
		Set se = new HashSet();
		//实例化1
		Person p1 = new Person("ZhangSan", 23, "male");
		//实例化2
		Person p2 = new Person("LiSi", 32, "female");
		//实例化3
		Person p3 = new Person("WangWu", 28, "male");
		//实例化4
		Person p4 = new Person("ZhaoLiu", 23, "female");
		//实例化5
		Person p5 = new Person("ZhangSan", 23, "male");
		//将实例化对象添加进集合中
		se.add(p1);
		se.add(p2);
		se.add(p3);
		se.add(p4);
		se.add(p5);
		//迭代集合中的元素
		Iterator<Person> it = se.iterator();
		//判断集合中是否存在元素
		while (it.hasNext()) {
			//迭代下一个元素
			Person per = it.next();
			//打印元素
			System.out.println(per);
		}
	}
}
package SetDemo;

//创建一个实体类
public class Person {
	private String name;
	private int age;
	private String sex;

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

	public Person() {
		super();
	}

	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;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	// 重写Object的tostring方法
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}

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

	// 重写Objet的equasl方法
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (sex == null) {
			if (other.sex != null)
				return false;
		} else if (!sex.equals(other.sex))
			return false;
		return true;
	}

}
结果为:
Person [name=WangWu, age=28, sex=male]
Person [name=LiSi, age=32, sex=female]
Person [name=ZhaoLiu, age=23, sex=female]
Person [name=ZhangSan, age=23, sex=male]

总结:hasHSet,底层是哈希表的数据结构,使用了HasCode和equals方法保证了元素的唯一性。


LinkedHashSet特征:
   1.LinkedHashSet是HashSet的子类,底层也是使用了哈希表的数据结构。
   2.它的数据是有序的,只不过它迭代的顺序是添加的顺序,因为它底层用链表来记录添加元素的顺序。迭代时,再使用添加时顺序迭代。
 LinkedHashSet实例:

public class ComparableDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// 创建一个Set集合的引用指向LinkedHashSet的对象
		Set se = new LinkedHashSet();
		// 实例化1
		Person p1 = new Person("ZhangSan", 23, "male");
		// 实例化2
		Person p2 = new Person("LiSi", 32, "female");
		// 实例化3
		Person p3 = new Person("WangWu", 28, "male");
		// 实例化4
		Person p4 = new Person("ZhaoLiu", 23, "female");
		// 实例化5
		Person p5 = new Person("ZhangSan", 23, "male");
		// 将实例化对象添加进集合中
		se.add(p1);
		se.add(p2);
		se.add(p3);
		se.add(p4);
		se.add(p5);
		// 迭代集合中的元素
		Iterator<Person> it = se.iterator();
		// 判断集合中是否存在元素
		while (it.hasNext()) {
			// 迭代下一个元素
			Person per = it.next();
			// 打印元素
			System.out.println(per);
		}
	}
}
结果为:
Person [name=ZhangSan, age=23, sex=male]
Person [name=LiSi, age=32, sex=female]
Person [name=WangWu, age=28, sex=male]
Person [name=ZhaoLiu, age=23, sex=female]

总结:LinkedHashSet集合是有序的,它结果的顺序是你添加元素的顺序,因为它底层用链表记录了添加元素的顺序。

TreeSet特征:
   1.它的元素是有序的,无重复元素。它的线程是不安全的
   2.它底层使用了二叉树的数据结构。
   3.二叉树的原理:
  1.它添加的第一个元素时根节点。
  2.再添加第二个元素时,与根节点进行比较,如果比根节点大,那么就放在根节点的右侧的子节点位置,如果比根节点小,那么就放在根节点的左侧子节点的位置,如果相等,那么就添加失败。
  3.添加第三个元素时,先与根节点进行比较,如果比根小,再与根的左侧比较,比它小放在它的左侧子节点,比它大放在它的右侧子节点。相等的话,添加失败。
       如果比根答,再与根的右侧比较,比它大放在它的右侧子节点,比它小放在它的左侧子节点。相等的话,添加失败。
   4.遍历二叉树的原则:先遍历左,然后当前,最后是右。
   5.TreeSet有序的原则:(1)TreeSet有比较器,那么使用比较器来比较元素 (2)TreeSet没有比较器,实现Comparable接口,让它具有自然顺序。

TreeSet实例:

import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

public class ComparableDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Comparator<Person> my = new Mycompare();
		// 创建一个Set集合的引用
		Set<Person> se = new TreeSet<Person>(my);
		// 实例化1
		Person p1 = new Person("ZhangSan", 23, "male");
		// 实例化2
		Person p2 = new Person("LiSi", 32, "female");
		// 实例化3
		Person p3 = new Person("WangWu", 28, "male");
		// 实例化4
		Person p4 = new Person("ZhaoLiu", 23, "female");
		// 实例化5
		Person p5 = new Person("ZhangSan", 23, "male");
		// 将实例化对象添加进集合中
		se.add(p1);
		se.add(p2);
		se.add(p3);
		se.add(p4);
		se.add(p5);
		// 迭代集合中的元素
		Iterator<Person> it = se.iterator();
		// 判断集合中是否存在元素
		while (it.hasNext()) {
			// 迭代下一个元素
			Person per = it.next();
			// 打印元素
			System.out.println(per);
		}
	}
}

class Mycompare implements Comparator<Person> {
	@Override
	public int compare(Person o1, Person o2) {
		// 从年龄开始比较
		int age = o1.getAge() - o2.getAge();
		if (age != 0) {
			return age;
		}
		// 如果年龄相等,从性别比较
		String o1sex = o1.getSex();
		String o2sex = o2.getSex();
		// 如果o1性别为男
		if (o1sex.equals("male")) {
			// 和如果o2性别为女,返回1,男大
			if (o2sex.equals("female")) {
				return -1;
			}
		} else {
			// 否则o2的性别为男时,o2比o1大
			if (o2sex.equals("male")) {
				return 1;
			}

		}

		return o1.getName().compareTo(o2.getName());
	}
}
结果:
Person [name=ZhangSan, age=23, sex=male]
Person [name=ZhaoLiu, age=23, sex=female]
Person [name=WangWu, age=28, sex=male]
Person [name=LiSi, age=32, sex=female]

总结:在进行比较时,如果判断元素不唯一,比如,同姓名,同年龄,才视为同一个人。在判断时,需要分主要条件和次要条件,当主要条件相同时,再判断次要条件,按照次要条件排序。

二、Map集合
 1、什么是Map集合?
  Map是双列集合,它是以Entry属性的键值对(Key.Value)的对象存在的。
 2、Map有什么特性?
  1.它是双列集合,Key键不能重复,Value值可以重复。
 3、Map有五种实现类。
  他们分别是:HashMap、TreeMap、HashTable、properties、LinkedHashMap、
      HashMap特征:
 1.它的底层是用哈希表的数据结构
 2.因为它的底层使用的是哈希表,所以它必须重写HashCode和equals方法。
 3.线程不同步的。可以存储null键,null值
 HashMap实例:

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MapDemo {

	/*
	 * 统计候选人票数是一个道理 所有投票人把自己心中的人选提交上来。
	 * 
	 * 张三把所有选票上的名字读一次,即循环遍历所有选票,并获取名字。 李四听到张三念一个,就在纸上找这个名字是否已经存在,如果存在,那么把票数+1
	 * 如果不存在,那么把这个名字写上,在票数上写1。
	 */
	public static void main(String[] args) {
		// 创建后候选人
		String s1 = "ZhanSan LiSi LiSi ZhanSan WangWu LiSi LiSi ZhanSan 张国荣";
		// 将返回的map创建成一个新的map集合
		Map<String, Integer> mp = fun(s1);
		// 将map集合转换为Set集合
		Set<Map.Entry<String, Integer>> entryset = mp.entrySet();
		// 遍历map集合
		for (Entry<String, Integer> s2 : entryset) {
			// 获取键
			String key = s2.getKey();
			// 获取值
			Integer vlaue = s2.getValue();
			// 将键和值打印
			System.out.println(key + "::" + vlaue);
		}
	}

	public static Map fun(String s1) {
		// 创建一个Map集合Map<String(候选人名字), Integer(票数)>
		Map<String, Integer> mp = new HashMap<String, Integer>();
		// 把参数字符串分隔成字符串数组;String[] names=s.split(" ");
		String[] names = s1.split(" ");
		// 循环遍历这个names
		for (int i = 0; i < names.length; i++) {
			int tokce = 1;
			// 判断mp中是否包含这个名字
			if (mp.containsKey(names[i])) {
				// 如果存在,获取票数(获取值),给值+1
				tokce = mp.get(names[i]) + 1;
			}
			mp.put(names[i], tokce);

		}
		return mp;

	}
}
结果为:
WangWu::1
张国荣::1
ZhanSan::3
LiSi::4

总结:Map自身没有遍历的方法,必须将其转换为Set集合然后遍历,转换的方法有两种:keySet();entrySet()

TreeMap特征:
  1.它的底层是用二叉树结构
  2.有序!使用键类型的自然顺序,或者TreeMap的比较器排序;
 多重Map集合实例:


import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// 创建一个大map中泛型左边类型的小map
		Map<String, String> gmsz = new LinkedHashMap<String, String>();
		// 创建大map中泛型的右边类型的小map
		Map<String, String> hjfw = new LinkedHashMap<String, String>();
		// 创建大map
		Map<String, Map<String, String>> mj = new LinkedHashMap<String, Map<String, String>>();
		// 向左边类型map添加元素
		gmsz.put("光明左使", "杨逍");
		gmsz.put("光明右使", "范遥");
		// 往右边类型map添加元素
		hjfw.put("紫衫龙王", "黛绮丝");
		hjfw.put("白眉鹰王", "殷天正");
		hjfw.put("金毛狮王", "谢逊");
		hjfw.put("青翼蝠王", "韦一笑");
		mj.put("光明使者", gmsz);
		mj.put("护教法王", hjfw);
		// 将大的map转换成set集合
		Set<String> keyset = mj.keySet();

		/*
		 * Iterator<String> it = keyset.iterator();
		 * 
		 * while (it.hasNext()) { String s1 = it.next(); Map<String, String> key
		 * = mj.get(s1); System.out.println(key); }
		 */
		// 使用高级for迭代set集合
		for (String st : keyset) {
			// 通过map的get方法获取键,返回右边小map的集合类型
			Map<String, String> st2 = mj.get(st);
			//将其打印
			System.out.println(st2);
		}

	}

}
结果:
{光明左使=杨逍, 光明右使=范遥}
{紫衫龙王=黛绮丝, 白眉鹰王=殷天正, 金毛狮王=谢逊, 青翼蝠王=韦一笑}

总结:Map集合主要是以键值对的形式存在,Entry就是键值对对象,Map结果都是以{}表示的,和list、set的不同。遍历Set的两种方法。KeySet和entrySet。KeySet中遍历的返回的是Value值的类型,entrySet中遍历返回的是Entry对象的返回值类型