一、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和Set2)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(); } }