java 集合
1 set 接口
set接口表示一个唯一的,无序的容器(和添加顺序无关)
1.1 set接口提供的方法
package set; import java.util.HashSet; import java.util.Set; public class Test01 { public static void main(String[] args) { /** * 增:add/addAll * 删:clear/remove/removeAll/retainAll * 改: * 查:contains/containsAll * 遍历:iterator * 其他:size/isEmpty */ Set<Integer> set = new HashSet<Integer>(); // [1]添加 // 无序 set.add(10); set.add(3); set.add(20); set.add(0); System.out.println(set); // 【2】删除 //set.remove(10); //set.clear(); //System.out.println(set); // 【3】查看是否包含 System.out.println(set.contains(0)); // 【4】其他 System.out.println(set.isEmpty()); System.out.println(set.size()); } } [0, 3, 20, 10] true false 4
1.2 Set接口的遍历
package set; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class Test02 { public static void main(String[] args) { Set<String> set = new HashSet<String>(); set.add("banana"); set.add("apple"); set.add("coco"); //快速遍历 for (String item : set) { System.out.println(item); } //迭代器 Iterator<String> it = set.iterator(); while (it.hasNext()) { String item = it.next(); System.out.println(it); } } } banana apple coco banana apple coco
set接口常见的实现类有HashSet LinkedHashSet TreeSet
1.3 HashSet 是set接口的实现类,底层数据结构是哈希表 线程是不安全的
1.4 添加自定义对象
根据哈希表的工作原理,请存储一个自定义对象到HashSet中。
package cn.sxt03.hashset; public class Student { private String id; private String name; private int age; // … @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((id == null) ? 0 : id.hashCode()); 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 (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; } }
【1】如果向HashSet中存储元素时,元素一定要实现hashCode方法和equals方法。
[2] 优点:添加、删除、查询效率高;缺点:无序
1.5 LinkedHashSet
LinkedHashSet是Set接口的实现类,底层数据结构哈希表+链表
哈希表用于散列元素;链表用于维持添加顺序。
如果要添加自定义对象元素,也需要重写hashCode和equals方法。
1.6 TreeSet
TreeSet 是Set接口的实现类,底层数据结构是二叉树。
TreeSet 存储的数据按照一定的规则存储。存储规则让数据表现出自然顺序。
添加一个新元素t的存储的步骤
[1] 如果集合无元素,t直接加入;如果集合有元素,t和根节点比较;
[2] 如果t小于根节点;把t放到根节点的左子树上;重复1-3步骤
[3] t大于根节点;把t放到根节点的右子树上;重复1-3步骤
输出时按照一定的规则:左子树->根节点->右子树
根据TreeSet的工作原理,向TreeSet添加自定义元素?
向TreeSet中添加元素时,一定要提供比较策略,否则会出现ClassCastException。
比较策略分两种:内部比较器和外部比较器
1.6 内部比较器
当一个自定义对象实现Comparable并实现compareTo方法时,通过指定具体的比较策略,此时称为内部比较器。
package set; public class Student implements Comparable<Student> { private String id; private String name; private int age; public Student() { super(); } public Student(String id, String name, int age) { super(); this.id = id; this.name = name; this.age = age; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; } @Override public int compareTo(Student o) {
/*if (this.getAge()<o.getAge()) {
return -1 ;
}else if (this.getAge()==o.getAge()) {
return 0;
}else {
if (this.getAge()>o.getAge()) {
return 1;
}*/
return this.getAge()-o.getAge();
}
}
package set; import java.util.TreeSet; public class Test03 { public static void main(String[] args) { TreeSet<Student> set = new TreeSet<Student>(); Student s1=new Student("001", "dagou", 20); Student s2=new Student("002", "2dagou", 21); Student s3=new Student("003", "3dagou", 22); set.add(s2); set.add(s3); set.add(s1); System.out.println(set); } } [Student [id=001, name=dagou, age=20], Student [id=002, name=2dagou, age=21], Student [id=003, name=3dagou, age=22]]
比较策略的几种情况
[1]比较策略一般当前对象写在前面,待比较对象也在后面,比较结果默认升序
return this.getAge() - o.getAge() ; |
如果想要降序,改变两个比较对象的位置即可。
[2] 多种比较因素
@Override public int compareTo(Student o) { /*if(this.getAge()<o.getAge()) { return -1; }else if(this.getAge() == o.getAge()) { return 0; }else { return 1; }*/ // return this.getAge() - o.getAge() ; if(this.getAge()<o.getAge()) { return -1; }else if(this.getAge() == o.getAge()) { return this.getName().compareTo(o.getName()); }else { return 1; } }
1.6 外部比较器
当实际开发过程中不知道添加元素的源代码、无权修改别人的代码,此时可以使用外部比较器。
Comparator 位于java.util包中,定义了compare(o1,o2) 用于提供外部比较策略。
TreeSet接受一个指定比较策略的构造方法,这些比较策略的实现类必须实现Comparator
接口。
需求:按照字符串的长度比较
package set; import java.util.Comparator; import java.util.TreeSet; public class Test04 { public static void main(String[] args) { LenComparator lenComparator = new LenComparator(); TreeSet<String> set2 = new TreeSet<String>(lenComparator); set2.add("banana"); set2.add("coco"); set2.add("apple"); set2.add("apple"); System.out.println(set2); } } class LenComparator implements Comparator<String>{ @Override public int compare(String o1, String o2) { return o1.length() - o2.length(); } } [coco, apple, banana]
1.7Map接口
Map接口称为键值对集合或者映射集合,其中的元素(entry)是以键值对(key-value)的形式存在。
Map 容器接口中提供了增、删、改、查的方式对集合进行操作。
Map接口中都是通过key来操作键值对,一般key是已知。通过key获取value。
1.8 map常用方法
package set; /** * 增:put/putAll * 删:clear/remove * 改:put * 查:get/containsKey/containsValue * 其他:isEmpty/size */ import java.util.HashMap; import java.util.Map; public class Test05 { public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); // 【1】put map.put("A", "apple"); map.put("B", "banana"); map.put("C", "coco"); System.out.println(map); // 【2】删除 //map.clear(); //map.remove("A"); //System.out.println(map); // 【3】修改 map.put("A", "apple X"); System.out.println(map); // 【4】查看 System.out.println(map.get("A")); System.out.println(map.containsKey("C")); System.out.println(map); } } {A=apple, B=banana, C=coco} {A=apple X, B=banana, C=coco} apple X true {A=apple X, B=banana, C=coco}
1.8 map接口的遍历
通过keySet() 返回map中键的set集合。
package set; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Test06 { public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); map.put("B", "apple"); map.put("A", "banana"); map.put("C", "coco"); // map无序 // 可以根据key的自然顺序 让map有序 => 一般用string作为key System.out.println(map); // 遍历 Set<String> keys = map.keySet(); for (String key : keys) { System.out.println(map.get(key)); } Iterator<String> it = keys.iterator(); while (it.hasNext()) { String key = it.next(); System.out.println(map.get(key)); } } } {A=banana, B=apple, C=coco} banana apple coco banana apple coco
map中以键值对作为元素,键值对在map中称为entry,entrySet返回键值对的set集合。
public static void main(String[] args) { Map<String, String> map = new HashMap<String,String>(); map.put("B", "banana"); map.put("A", "apple"); map.put("C", "coco"); // map无序 // 可以根据key的自然顺序 让map有序 => 一般用string作为key System.out.println(map); // entrySet Set<Entry<String, String>> entrySet = map.entrySet(); for (Entry<String, String> entry : entrySet) { System.out.println(entry.getKey()+"=>"+entry.getValue()); } Iterator<Entry<String, String>> it2 = entrySet.iterator(); while(it2.hasNext()) { Entry<String, String> entry = it2.next(); System.out.println(entry.getKey()+"=>"+entry.getValue()); } }
Map接口的实现类HashMap、LinkedHashMap、TreeMap
1.10 HashMap
HashMap 是Map的实现类,key以HashSet存储。
public static void main(String[] args) { /* HashMap<String, Object> map = new HashMap<String,Object>(); ArrayList<String> list1 = new ArrayList<String>(); list1.add("alex"); list1.add("alice"); list1.add("allen"); map.put("A", list1); ArrayList<String> list2 = new ArrayList<String>(); list2.add("ben"); list2.add("bill"); map.put("B", list2); System.out.println(map); */ HashMap<Student, Object> map = new HashMap<Student,Object>(); ArrayList<String> list1 = new ArrayList<String>(); list1.add("alex"); list1.add("alice"); list1.add("allen"); Student s1 = new Student("001", "大狗", 20); map.put(s1, list1); ArrayList<String> list2 = new ArrayList<String>(); list2.add("ben"); list2.add("bill"); Student s2 = new Student("001", "大狗", 20); // 修改 map.put(s2, list2); System.out.println(map); }
[1] 向HashMap中存储元素时,key一定要实现hashCode和equals
[2] 一般建议使用String作为Map接口的key
1.11 LinkedHashMap
LinkedHashMap是Map接口的实现类,key以LinkedHashSet存储。
哈希表散列key,链表维持key的添加顺序。
public static void main(String[] args) { /*LinkedHashMap<String, Object> map = new LinkedHashMap<String,Object>(); ArrayList<String> list2 = new ArrayList<String>(); list2.add("ben"); list2.add("bill"); map.put("B", list2); ArrayList<String> list1 = new ArrayList<String>(); list1.add("alex"); list1.add("alice"); list1.add("allen"); map.put("A", list1); System.out.println(map);*/ HashMap<Student, Object> map = new HashMap<Student,Object>(); ArrayList<String> list1 = new ArrayList<String>(); list1.add("alex"); list1.add("alice"); list1.add("allen"); Student s1 = new Student("001", "大狗", 20); map.put(s1, list1); ArrayList<String> list2 = new ArrayList<String>(); list2.add("ben"); list2.add("bill"); Student s2 = new Student("001", "大狗", 20); // 修改 map.put(s2, list2); System.out.println(map); }
1.12 TreeMap
TreeMap是Map的实现类,key以TreeSet存储。
public static void main(String[] args) { /*TreeMap<String, Object> map = new TreeMap<String,Object>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.length() - o2.length(); } }); ArrayList<String> list2 = new ArrayList<String>(); list2.add("ben"); list2.add("bill"); map.put("Aa", list2); ArrayList<String> list1 = new ArrayList<String>(); list1.add("alex"); list1.add("alice"); list1.add("allen"); map.put("B", list1); System.out.println(map);*/ TreeMap<Student, Object> map = new TreeMap<Student,Object>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } }); ArrayList<String> list1 = new ArrayList<String>(); list1.add("alex"); list1.add("alice"); list1.add("allen"); Student s1 = new Student("001", "大狗", 20); map.put(s1, list1); ArrayList<String> list2 = new ArrayList<String>(); list2.add("ben"); list2.add("bill"); Student s2 = new Student("001", "2狗", 20); // 修改 map.put(s2, list2); System.out.println(map); }