Set接口概述:
一个不包含重复元素的collection。
Collection
List
有序(存储顺序和取出顺序一致),可重复
Set
无序(存储顺序和取出顺序不一致),唯一
HashSet:它不保证Set的迭代顺序;特别是它不保证顺序恒久不变。
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo {
public static void main(String[] args) {
//创建集合
Set<String> set = new HashSet<String>();
// set.add("hello");
// set.add("world");
// set.add("java");
//
// //增强for
// for(String s : set) {
// System.out.println(s);
// }
// world
// java
// hello
set.add("hello");
set.add("world");
set.add("java");
set.add("world");
set.add("java");
//增强for
for(String s : set) {
System.out.println(s);
}
// world
// java
// hello
}
}
HashSet:存储字符串的唯一性
查看add()方法源码,方法底层依赖两个方法:hashCode()和equals()。
步骤:
首先比较哈希值
如果相同,继续比较地址值或者equals()
如果不同,就直接添加到集合中
先看hashCode()值是否相同
相同:继续equals()方法。
返回true:说明元素重复,就不添加
返回false:说明元素不重复,就添加到集合
不相同:就直接把元素添加到集合
如果类没有重写这两个方法,默认使用Object类中方法。一般不会相同。
而String类重写了hashCode()和equals()方法,所以,它就可以把内容相同的字符串去掉。保证唯一性。
HashSet存储自定义对象
注意:需要重写hashCode()方法和equals()方法(可自动生成)。优化hashCode()方法让对象的哈希值尽可能的不同。(由于哈希值和对象的成员变量值相关,所以,最终解决方案就是把对象的成员变量值进行相加:如果是基本类型,就直接加值;如果是引用类型,就加哈希值)
public 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;
}
}
import java.util.HashSet;
public class HashSetDemo2 {
public static void main(String[] args) {
// 创建集合
HashSet<Student> hashSet = new HashSet<Student>();
// 创建学生对象
Student s = new Student("刘备", 30);
Student s2 = new Student("关羽", 27);
Student s3 = new Student("张飞", 26);
Student s4 = new Student("刘备", 30);
Student s5 = new Student("关羽", 28);
Student s6 = new Student("刘备", 27);
Student s7 = new Student("张飞", 26);
hashSet.add(s);
hashSet.add(s2);
hashSet.add(s3);
hashSet.add(s4);
hashSet.add(s5);
hashSet.add(s6);
hashSet.add(s7);
for(Student ss : hashSet) {
System.out.println(ss.getName()+"---"+ss.getAge());
}
}
}
----------------------------------------------------------------------
关羽---28
刘备---30
张飞---26
关羽---27
刘备---27
LinkedHashSet:底层数据结构由哈希表和链表组成。
哈希表保证元素的唯一性。
链表保证元素有序。(存储和取出是一致)
TreeSet类概述:能够对元素按照某种规则进行排序
使用元素的自然顺序对元素进行排序
或者根据创建set时提供的Comparator(比较器)进行排序
具体取决于使用的构造方法。
TreeSet集合的特点:排序和唯一
排序的真正比较是依赖与元素的compareTo()方法,而这个方法是定义在Comparable接口里面的。所以,重写该方法,必须实现实现Comparable接口。这个接口表示的就是自然排序。
TreeSet:底层是二叉树结构。(红黑树是一种自平衡的二叉树)
元素存储规则:
第一个元素存储时,直接作为根节点存储。
从第二个元素开始,每个元素从根节点开始比较
若大 作为右孩子
若小 作为左孩子
若相等 则不存储
前序遍历输出,实现排序及唯一。
TreeSet存储自定义对象并保证排序和唯一。自定义对象需要根据自定义对象的自然排序规则实现自然排序Comparable接口并重写CompareTo()方法。
TreeSet集合保证元素排序和唯一性的原理
唯一性:是根据比较的返回是否是0来决定。
排序:
A:自然排序(元素具备比较性)
让元素所属的类实现自然排序接口Comparable
B:比较器排序(集合具备比较性)
让集合的构造方法接收一个比较器接口的子类对象Comparator
public class Student implements Comparable<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 compareTo(Student s) {
int num = this.age - s.age;
int num2 = num == 0 ? this.name.compareTo(s.name) : num;
return num2;
}
}
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<Student>();
Student s = new Student("刘备", 30);
Student s2 = new Student("关羽", 27);
Student s3 = new Student("张飞", 26);
Student s4 = new Student("刘备", 30);
Student s5 = new Student("关羽", 28);
Student s6 = new Student("刘备", 27);
Student s7 = new Student("张飞", 26);
treeSet.add(s);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
treeSet.add(s6);
treeSet.add(s7);
for(Student ss : treeSet) {
System.out.println(ss.getName()+"---"+ss.getAge());
}
}
}
---------------------------------------------------------------------------------------------------
张飞---26
关羽---27
刘备---27
关羽---28
刘备---30
匿名内部类实现比较器排序。
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getAge() - s2.getAge();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
return num2;
}
});
Student s = new Student("刘备", 30);
Student s2 = new Student("关羽", 27);
Student s3 = new Student("张飞", 26);
Student s4 = new Student("刘备", 30);
Student s5 = new Student("关羽", 28);
Student s6 = new Student("刘备", 27);
Student s7 = new Student("张飞", 26);
treeSet.add(s);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
treeSet.add(s6);
treeSet.add(s7);
for(Student ss : treeSet) {
System.out.println(ss.getName()+"---"+ss.getAge());
}
}
}
Map集合的特点:
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
Map集合和Collection集合的区别?
Map集合存储元素是成对出现的,Map集合的键是唯一的,值是可重复的。
Collection集合存储元素是单独出现的,Collection的儿子Set是唯一的,List是可重复的。
注意:
Map集合的数据结构值针对键有效,跟值无关
Collection集合的数据结构是针对元素有效
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():返回集合中的键值对的对数
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
//遍历Map集合的两种方法
public class HashMapDemo {
public static void main(String[] args) {
// 创建集合
Map<String, String> map = new HashMap<String, String>();
map.put("杨过", "小龙女");
map.put("郭靖", "黄蓉");
map.put("张无忌", "周芷若");
map.put("梁山伯", "祝英台");
map.put("杰克", "露西");
//获取所有键的集合
Set<String> set = map.keySet();
//根据键获取值进行遍历
for(String s : set) {
System.out.println(s+"---"+map.get(s));
}
System.out.println("----------------------------");
Set<Map.Entry<String, String>> set2 = map.entrySet();
for(Map.Entry<String, String> map2 : set2) {
System.out.println(map2.getKey()+"---"+map2.getValue());
}
}
}
HashMap类概述
键是哈希表结构,可以保证键的唯一性
知识点:
java中数值类型进制表示
二进制:0b****;(*表示0或1)
八进制:0****;(*表示0到7任意数字)
十六进制:0x****;(*表示0到f任意数字)
LinkedHashMap:是Map接口的哈希表和链表实现,具有可预知的迭代顺序。
由哈希表保证键的唯一性
由链表保证键盘的有序(存储和取出的顺序一致)
TreeMap类概述:
键是红黑树结构,可以保证键的排序和唯一性。
//嵌套集合
/*
* 升达
* cj 财经学院
* kj 会计专业
* 林黛玉 25
* 薛宝钗 28
* cwgl 财务管理
* 贾宝玉 26
* 王熙凤 29
* xg 信工学院
* rjgc 软件工程
* 赵云 26
* 马超 27
* jk 计科专业
* 关羽 28
* 黄忠 30
* jg 建工学院
* tmgc 土木工程
* 宋江 37
* 李逵 32
* gcgl 工程管理
* 吴用 28
* 鲁智深 33
*
*
* */
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class HashMapDemo2 {
public static void main(String[] args) {
// 创建升达集合
HashMap<String, HashMap<String, ArrayList<Student>>> sdmap = new HashMap<String, HashMap<String, ArrayList<Student>>>();
// 财经集合
HashMap<String, ArrayList<Student>> cjmap = new HashMap<String, ArrayList<Student>>();
// 会计集合
ArrayList<Student> kjList = new ArrayList<Student>();
Student s1 = new Student("林黛玉", 25);
Student s2 = new Student("薛宝钗", 28);
kjList.add(s1);
kjList.add(s2);
// 财务管理集合
ArrayList<Student> cwglList = new ArrayList<Student>();
Student s3 = new Student("贾宝玉", 26);
Student s4 = new Student("王熙凤", 29);
cwglList.add(s3);
cwglList.add(s4);
cjmap.put("会计专业", kjList);
cjmap.put("财务管理", cwglList);
// 信工集合
HashMap<String, ArrayList<Student>> xgmap = new HashMap<String, ArrayList<Student>>();
// 软工集合
ArrayList<Student> rgList = new ArrayList<Student>();
Student s5 = new Student("赵云", 26);
Student s6 = new Student("马超", 27);
rgList.add(s5);
rgList.add(s6);
// 计科集合
ArrayList<Student> jkList = new ArrayList<Student>();
Student s7 = new Student("关羽", 28);
Student s8 = new Student("黄忠", 30);
jkList.add(s7);
jkList.add(s8);
xgmap.put("软件工程", rgList);
xgmap.put("计科专业", jkList);
// 建工集合
HashMap<String, ArrayList<Student>> jgmap = new HashMap<String, ArrayList<Student>>();
// 土木工程集合
ArrayList<Student> tmList = new ArrayList<Student>();
Student s9 = new Student("宋江", 37);
Student s10 = new Student("李逵", 32);
tmList.add(s9);
tmList.add(s10);
// 工程管理集合
ArrayList<Student> gcList = new ArrayList<Student>();
Student s11 = new Student("吴用", 28);
Student s12 = new Student("鲁智深", 33);
gcList.add(s11);
gcList.add(s12);
jgmap.put("土木工程", tmList);
jgmap.put("工程管理", gcList);
sdmap.put("财经学院", cjmap);
sdmap.put("信工学院", xgmap);
sdmap.put("建工学院", jgmap);
//遍历集合
Set<String> sdSet = sdmap.keySet();
for(String sdKey : sdSet) {
System.out.println(sdKey);
HashMap<String,ArrayList<Student>> sdValue = sdmap.get(sdKey);
Set<String> xySet = sdValue.keySet();
for(String xyKey : xySet) {
System.out.println("\t"+xyKey);
ArrayList<Student> zyList = sdValue.get(xyKey);
for(Student s : zyList) {
System.out.println("\t\t"+s.getName()+"---"+s.getAge());
}
}
}
}
}
---------------------------------------------------------------------------------------------------------------
财经学院
会计专业
林黛玉---25
薛宝钗---28
财务管理
贾宝玉---26
王熙凤---29
信工学院
软件工程
赵云---26
马超---27
计科专业
关羽---28
黄忠---30
建工学院
工程管理
吴用---28
鲁智深---33
土木工程
宋江---37
李逵---32
Hashtable和HashMap的区别?
Hashtable:线程安全,效率低。不允许null键和null值
HashMap:线程不安全,效率高。允许null键和null值
List,Set,Map等接口是否都继承自Map接口?
List,Set不是继承自Map接口,它们继承自Collection接口
Map接口本身就是一个顶层接口
Collections类概述
针对集合操作的工具类,都是静态方法。
Collection和Collections的区别?
Collection:是单列集合的顶层接口,有子接口List和Set。
Collections:是针对集合操作的工具类,有对集合进行排序和二分查找的方法。
Collections类方法:
public static <T> void sort(List<T> list):排序 默认情况下是自然排序。
public static <T> int binarySearch(List<?> list,T key):二分查找
public static <T> T max(Collection<?> coll):最大值
public static void reverse(List<?> list):反转
public static void shuffle(List<?> list):随机置换