一、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对象的返回值类型