集合框架(二)
4.Set子接口
- 特点:无序、无下标、元素不可重复。
- 方法:全部继承自Collection中的方法
set实现类
- HashSet【重点】:
- 基于HashCode实现元素不重复
- 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入
- TreeSet:
- 基于排列顺序事项元素不重复
- 实现了SortedSet接口,对集合元素自动排列
- 元素对象的类型必须实现Comparable 接口,指定排序规则
- 通过CompareTo方法确认是否为重复元素
1.Set接口的使用
Set子接口的使用和之前的Collection父接口方法相同
package com.collection.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/*
测试Set接口的使用
特点:无序、无下标、元素不能重复
*/
public class Demo01 {
public static void main(String[] args) {
//创建集合
Set<String> set = new HashSet<>();
//添加数据
set.add("华为");
set.add("小米");
set.add("苹果");
System.out.println("元素个数"+set.size());
System.out.println(set.toString());
//删除
set.remove("小米");
System.out.println(set.toString());
//遍历【重点】
for (String string : set) {
System.out.println(string);
}
//迭代器
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//判断
System.out.println(set.contains("苹果"));
System.out.println(set.isEmpty());
}
}
2.HashSet的使用
- 增、删、遍历、判断和之前的方法一样
- 存储结构:哈希表(数组+链表+红黑树)
例1:
package com.collection.Set;
import java.util.HashSet;
import java.util.Iterator;
/*
HashSet集合的使用
存储结构:哈希表(数组+链表+红黑树)
*/
public class Demo02 {
public static void main(String[] args) {
//新建集合
HashSet<String> hashSet = new HashSet<>();
//添加元素
hashSet.add("刘德华");
hashSet.add("梁朝伟");
hashSet.add("林志玲");
hashSet.add("周润发");
System.out.println("元素个数"+hashSet.size());
System.out.println(hashSet.toString());
//删除数据
hashSet.remove("刘德华");
System.out.println(hashSet.size());
//遍历
for (String string : hashSet) {
System.out.println(string);
}
Iterator<String> iterator = hashSet.iterator();
while ((iterator.hasNext())) {
System.out.println(iterator.next());
}
//判断
System.out.println(hashSet.contains("林志玲"));
System.out.println(hashSet.isEmpty());
}
}
- 存储过程(重复的依据)
(1)根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步
(2)再执行equals方法,如果为true,则认为是重复,否则,形成链表
persons.add(new Person("梁朝伟", 24));//重写了hashcode和equals
//手写:
// @Override
// public int hashCode() {
// int n1 = this.name.hashCode();
// int n2 = this.age;
// return n1+n2;
// }
//
// @Override
// public boolean equals(Object obj) {
// if(this == obj){
// return true;
// }
// if(obj == null){
// return false;
// }
// if(obj instanceof Person){
// Person p = (Person)obj;
// if(this.name.equals(p.getName())&&this.age == p.getAge()){
// return true;
// }
// }
// return false;
// }
//idea 自动生成:
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
Person person = (Person) object;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
实例2:
package com.collection.Set;
import java.util.HashSet;
import java.util.Iterator;
/*
存储过程(重复的依据)
(1)根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步
(2)再执行equals方法,如果为true,则认为是重复,否则,形成链表
*/
public class Demo03 {
public static void main(String[] args) {
//创建集合
HashSet<Person> persons = new HashSet<>();
//添加数据
Person p1 = new Person("刘德华", 20);
Person p2 = new Person("林志玲", 22);
Person p3 = new Person("梁朝伟", 24);
persons.add(p1);
persons.add(p2);
persons.add(p3);
//persons.add(p3);重复不能添加
persons.add(new Person("梁朝伟", 24));//重写了hashcode和equals
System.out.println("元素个数:"+persons.size());
System.out.println(persons.toString());
//删除
persons.remove(p1);
System.out.println(persons.size());
//遍历
for (Person person : persons) {
System.out.println(person.toString());
}
Iterator<Person> it = persons.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//4.判断
System.out.println(persons.contains(p2));
System.out.println(persons.isEmpty());
//
}
}
3.TreeSet的使用
- 方法的使用与HashSet相同
- 存储结构:红黑树 会有排序
package com.collection.Set;
import java.util.Iterator;
import java.util.TreeSet;
/*
TreeSet的使用
存储结构:红黑树
*/
public class Demo04 {
public static void main(String[] args) {
TreeSet<String> treeSet = new TreeSet<>();
//添加
treeSet.add("xyz");
treeSet.add("abc");
treeSet.add("hello");
treeSet.add("xyz");
System.out.println(treeSet.size());
System.out.println(treeSet.toString());
//删除
treeSet.remove("abc");
System.out.println(treeSet.size());
//遍历
for (String string : treeSet) {
System.out.println(string);
}
Iterator<String> it = treeSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//判断
System.out.println(treeSet.contains("xyz"));
System.out.println(treeSet.isEmpty());
}
}
使用复杂类型:
- 要求:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
- 添加元素时要重写compareTo()方法
package com.collection.Set;
import java.util.Objects;
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
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 String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//先按姓名来比,然后再按年龄比
@Override
public int compareTo(Person o) {
int n1 = this.getName().compareTo(o.getName());
int n2 = this.age - o.getAge();
return n1 == 0 ? n2 : n1;
}
}
例2:
package com.collection.Set;
import java.util.Iterator;
import java.util.TreeSet;
/*
使用TreeSet保证数据
要求:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
*/
public class Demo05 {
public static void main(String[] args) {
TreeSet<Person> persons = new TreeSet<>();
//添加
Person p1 = new Person("xyz", 20);
Person p2 = new Person("hello", 22);
Person p3 = new Person("zhangsan", 24);
persons.add(p1);
persons.add(p2);
persons.add(p3);
System.out.println(persons.size());
System.out.println(persons.toString());
//删除
persons.remove(p1);
System.out.println(persons.size());
//遍历
for (Person person : persons) {
System.out.println(person);
}
Iterator<Person> iterator = persons.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
//判断
System.out.println(persons.contains(p2));
System.out.println(persons.isEmpty());
}
}
Compareor接口
Comparator:实现定制比较(比较器),就不需要连接Comparable接口了
Comparable:可比较的
package com.collection.Set;
import java.util.Comparator;
import java.util.TreeSet;
/*
TreeSet的使用
Comparator:实现定制比较(比较器)
Comparable:可比较的
*/
public class Demo06 {
public static void main(String[] args) {
//创建集合,并指定比较规则
TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {//使用匿名内部类
@Override
public int compare(Person o1, Person o2) {
int n1 = o1.getAge() - o2.getAge();
int n2 = o1.getName().compareTo(o2.getName());
return n1 == 0 ? n2 : n1;
}
});
Person p1 = new Person("刘德华", 20);
Person p2 = new Person("林志玲", 22);
Person p3 = new Person("梁朝伟", 24);
persons.add(p1);
persons.add(p2);
persons.add(p3);
System.out.println(persons.toString());
}
}
TreeSet案例
使用TreeSet集合实现字符串按照长度进行排序:
package com.collection.Set;
import java.util.Comparator;
import java.util.TreeSet;
/*
使用TreeSet集合实现字符串按照长度进行排序
helloworld zhang lisi wangwu beijing xian nanjing
Comparator接口实现定制比较
*/
public class Demo07 {
public static void main(String[] args) {
//创建集合,并指定比较规则
TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int n1 = o1.length() - o2.length();
int n2 = o1.compareTo(o2);
return n1 == 0?n2:n1;
}
});
//添加数据
treeSet.add("helloworld");
treeSet.add("zhang");
treeSet.add("lisi");
treeSet.add("beijing");
treeSet.add("xian");
treeSet.add("nanjing");
System.out.println(treeSet.size());
System.out.println(treeSet.toString());
}
}
5.Map集合

)
- Map接口的特点
- 用于存储任意键值对(Key--Value)
- 键:无序、无下标、不允许重复(唯一)
- 值:无序、无下标、允许重复
1.Map父接口
- 特点:存储一对数据(Key--Value),无序、无下标、键不可重复,值可以重复
- 方法:
- V put(K key,V value):将对象存入集合中,关联键值。key重复则覆盖原来的值
- Object get(Object key):根据键获取对应的值。
- keySet
:返回所有的key - Collection
values():返回包含所有值的Collection集合 - Set<Map.Entry<K,V>>:键值匹配的Set集合
2.Map接口的基本使用
package com.collection.Map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
Map接口的使用
特点:(1)存储键值对(2)键不能重复,值可以重复(3)无序
*/
public class Demo01 {
public static void main(String[] args) {
//创建Map集合
Map<String,String> map = new HashMap<>();
//添加元素
map.put("cn","中国");
map.put("uk","英国");
map.put("usa","美国");
map.put("cn","zhongguo");//key重复则覆盖原来的值
System.out.println(map.size());//元素个数
System.out.println(map.toString());
//删除
// map.remove("usa");
// System.out.println("删除之后:"+map.size());
//遍历
//3.1.使用keySet();
//Set<String> keyset = map.keySet();
for (String key : map.keySet()) {
System.out.println(key+"-------"+map.get(key));
}
//3.2.使用entrySet()方法(效率更高)
//Set<Map.Entry<String, String>> entryset = map.entrySet();
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey()+"-------"+entry.getValue());
}
//4.判断
System.out.println(map.containsKey("cn"));
System.out.println(map.containsValue("zhongguo"));
}
}
3.Map集合的实现类
- HashMap【重点】
- JDK1.2版本,线程不安全,运行效率快;允许用null作为key或者是value
- Hashtable(了解)
- jdk1.0版本,线程安全,运行效率慢;不允许null作为key或是value
- Properties:
- Hashtable的子类,要求key和value都是String。通常用于配置文件的读取
- TreeMap
- 实现了SortedMap接口(是Map的子接口),可以对key自动排序
HashMap的使用
package com.collection.Map;
import java.util.HashMap;
import java.util.Map;
/*
HashMap集合的使用
存储接结构:哈希表(数组+链表+红黑树)
使用key可用hashcode和equals作为重复
*/
public class Demo02 {
public static void main(String[] args) {
HashMap<Student, String> students = new HashMap<>();
//刚创建hashMap之后没有添加元素table=null size=0 目的是节省空间
//添加
Student s1 = new Student("孙悟空", 100);
Student s2 = new Student("猪八戒", 101);
Student s3 = new Student("沙和尚", 102);
students.put(s1,"北京");
students.put(s2,"上海");
students.put(s3,"杭州");
students.put(new Student("沙和尚", 102),"浙江");//重写hashcode 和 equals
System.out.println(students.size());
System.out.println(students.toString());
//删除
students.remove(s1);
System.out.println("删除之后"+students.size());
//遍历
//使用keySet();
for (Student key: students.keySet()) {
System.out.println(key.toString()+"--------"+students.get(key));
}
//使用entrySet()
for (Map.Entry<Student, String> entry : students.entrySet()) {
System.out.println(entry.getKey()+"--------"+entry.getValue());
}
//判断
System.out.println(students.containsKey(new Student("猪八戒", 101)));
System.out.println(students.containsValue("杭州"));
}
}
源码分析:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //hashMap初始容量大小
static final int MAXIMUM_CAPACITY = 1 << 30; //hashMap 的数组最大容量
static final float DEFAULT_LOAD_FACTOR = 0.75f; //默认加载因子
static final int TREEIFY_THRESHOLD = 8; //jdk1.8 当链表长度大于8时,调整成红黑树
static final int UNTREEIFY_THRESHOLD = 6; //jdk1.8 当链表长度小于6时,调整成链表
static final int MIN_TREEIFY_CAPACITY = 64; //jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,跳转成红黑树
transient Node<K,V>[] table; //哈希表中的数组
源编总结:
- HashMap刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16.
- 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数
- jdk1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整成红黑树,目的是提高执行效率
- jdk1.8 当链表长度小于6时,调整成链表
- jdk1.8以前,链表是头插入,jdk1.8以后是尾插
TreeMap的使用
package com.collection.Map;
import java.util.Map;
import java.util.TreeMap;
/*
TreeMap的使用
存储结构:红黑树
*/
public class Demo03 {
public static void main(String[] args) {
//新建集合(也可以使用定制比较)
TreeMap<Student, String> treeMap = new TreeMap<Student,String>();
//1.添加元素
Student s1 = new Student("孙悟空", 100);
Student s2 = new Student("猪八戒", 101);
Student s3 = new Student("沙和尚", 102);
//添加需要重写compareTo
treeMap.put(s1,"北京");
treeMap.put(s2,"上海");
treeMap.put(s3,"深圳");
treeMap.put(new Student("沙和尚", 102),"南京");
System.out.println("元素个数:"+treeMap.size());
System.out.println(treeMap.toString());
//删除
// treeMap.remove(s3);
// System.out.println(treeMap.size());
//遍历
//使用keySet
for (Student key : treeMap.keySet()) {
System.out.println(key+"---------"+treeMap.get(key));
}
//使用entrySet
for (Map.Entry<Student, String> entry : treeMap.entrySet()) {
System.out.println(entry.getKey()+"---------"+entry.getValue());
}
//判断
System.out.println(treeMap.containsKey(s3));
System.out.println(treeMap.containsValue("南京"));
}
}
6.Collections工具类
- 概念:集合工具类,定义了除了存取以外的集合常用的方法
- 方法:
- public static void reverse(List<?> list ):反转集合中元素的顺序
- public static void shuffle(List<?> list):随机重置集合元素的顺序
- public static void sort(List<?> list):升序排序(元素类型必须实现Comparable接口)
package com.collection.Collectiontool;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/*
演示Collection工具类的使用
*/
public class Demo01 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(20);
list.add(5);
list.add(12);
list.add(30);
list.add(6);
//sort 排序
System.out.println("排序前:"+list.toString());
Collections.sort(list);
System.out.println("排序后:"+list.toString());
//binarySearch 二分查找
int i = Collections.binarySearch(list, 12);
System.out.println(i);
//copy复制
List<Integer> dest = new ArrayList<>();//在无数据时size为0,故要先添加一个元素
for (int k=0; k< list.size();k++){
dest.add(0);
}
Collections.copy(dest, list);//要保证集合大小相等才行
System.out.println(dest.toString());
//reverse反转
Collections.reverse(list);
System.out.println("反转之后"+list.toString());
//shuffle 打乱
Collections.shuffle(list);
System.out.println("打乱之后:"+list.toString());
//补充:list转成数组
Integer[] array = list.toArray(new Integer[0]);//当list中的长度小于所设置的长度,其数组长度与list长度相等
System.out.println(Arrays.toString(array));
//数组转成集合
String[] name = {"张三","李四","王五"};
//集合是一个受限集合,不能添加和删除 因为数组的大小已经固定。
List<String> list2 = Arrays.asList(name);
System.out.println(list2.toString());
//把基本类型数组转换为集合时,需要修改为包装类型
Integer[] num2 = {100,200,300,400};
List<Integer> list3 = Arrays.asList(num2);
System.out.println(list3.toString());
}
}

浙公网安备 33010602011771号