集合
集合的特点
- 集合是java中存储对象的一种容器
- 集合的大小不固定,启动后可以动态变化,类型也可以选择不固定
- 集合非常适合做元素的增删操作
- 集合支持泛型
- 注意:集合中只能存储引用类型数据,不支持基本类型,但可使用包装类
集合类体系结构
-
Collection单列集合
每个元素只包含一个值
-
Map双列集合
每个元素包含两个值
Collection集合体系
-
List系列集合:添加的元素是有序、可重复、有索引
- ArrayList、LinkedList有序、可重复、有索引
-
Set系列集合:添加的元素是无序、不重复、无索引
- HashSet:无序、不重复、无索引;LinkedHashSet:有序、不重复、无索引;
- TreeSet:按照大小默认升序、不重复、无索引
package demo6;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
public class Test1 {
public static void main(String[] args) {
Collection list = new ArrayList();
list.add("java");
list.add("java");
list.add(23);
list.add(true);
list.add(false);
System.out.println(list);
Collection list1 = new HashSet();
list1.add("java");
list1.add("java");
list1.add(23);
list1.add(true);
list1.add(false);
System.out.println(list1);
Collection<String> list2 = new ArrayList<>();
list2.add("java");
// list2.add(123);
Collection<Integer> list3 = new ArrayList<>();
list3.add(123);
System.out.println(list2 + "\t" + list3);
}
}
Collection集合常用API
package demo6;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
public class Test2 {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
c.add("java");
c.add("c++");
c.add("c#");
System.out.println(c);
// //清空
// c.clear();
//判空
System.out.println(c.isEmpty());
//获取大小
System.out.println(c.size());
//判断是否包含某元素
System.out.println(c.contains("java"));
//删除某元素,如重复,默认删除第一个
System.out.println(c.remove("java"));
System.out.println(c);
//集合转化为数组
Object[] arrs = c.toArray();
System.out.println(Arrays.toString(arrs));
}
}
package demo6;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;
public class Test3 {
public static void main(String[] args) {
Collection<String> lists = new ArrayList<>();
lists.add("张三");
lists.add("李四");
lists.add("王五");
lists.add("刘二麻子");
System.out.println(lists);
//迭代器
Iterator<String> it = lists.iterator();
// while (it.hasNext()) {
// System.out.println(it.next());
// }
// for (String ele : lists) {
// System.out.println(ele);
// }
lists.forEach(s -> {
System.out.println(s);
});
}
}
List系列集合
- List集合特有方法
package demo6;
import java.util.ArrayList;
import java.util.List;
public class Test4 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("java");
list.add("java");
list.add("MySQL");
list.add("MySQL");
list.add(2, "c#");
System.out.println(list);
System.out.println(list.remove(2));
System.out.println(list.get(2));
System.out.println(list.set(1, "c++"));
}
}
- ArrayList底层是基于数组实现的,根据查询元素快,增删相对慢
- LinkedList底层基于双链表实现,查询元素慢,增删首尾元素非常快
Set系列集合
- JDK8之前的哈希表:底层使用数组+链表
- JDK8之后的哈希表:底层使用数组+链表+红黑树
哈希表流程:
- 创建一个默认长度16,默认加载因子0.75的数组,数组名为table
- 根据元素的哈希值跟数组长度计算出应存入的位置
- 判断当前位置是否为null,如果是null直接存入,如果不为null,表示有元素,则调用equals方法比较属性值,如果一样,则不存,不过不一样,存入
- 当数组存满到16*0.75=12时,就自动扩容,每次扩容原先的两倍
HashSet
- 数组存取
package demo7;
import java.util.Objects;
public class Student {
private String name;
private int age;
private char sex;
public Student() {
}
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 char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public Student(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && sex == student.sex && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, sex);
}
}
package demo7;
import java.util.HashSet;
import java.util.Set;
public class Test1 {
public static void main(String[] args) {
Set<Student> sets = new HashSet<>();
Student s1 = new Student("张三", 20, '男');
Student s2 = new Student("张三", 20, '男');
Student s3 = new Student("李四", 18, '女');
sets.add(s1);
sets.add(s2);
sets.add(s3);
System.out.println(s1.hashCode() + "\t" + s2.hashCode());
System.out.println(s1.equals(s2));
}
}
LinkHashSet
- 底层基于哈希表,使用双链表记录添加顺序
TreeSet
- 底层基于红黑树的数据结构实现排序,增删改查性能都较好
- 注意:TreeSet集合一定要排序,可以将元素按照制定规则进行排序
- 对于数值类型:Integer,Double,默认升序
- 对于字符串类型:默认首字符编号升序
- 自定义类型无法排序
TreeSet集合自定义排序方式:
- 类实现Comparable接口,重写比较规则
- 集合自定义Comparator比较对象,重写比较规则
Map集合体系
- Map集合的特点都由键决定的
- Map集合的键是无序、不重复、无索引的,值不做要求
- Map集合后面重复的键对应的值会覆盖前面重复键的值
- Map集合的键值对都可以为null
Map集合实现类特点
- HashMap:元素按照键是无序、不重复、无索引的,值不做要求
- LinkedHashMap:元素按照键是有序、不重复、无索引的,值不做要求
- TreeMap:元素按照键是排序、不重复、无索引的,值不做要求
Map集合常用API
Map集合的遍历方式
- 键找值
package demo9;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test01 {
public static void main(String[] args) {
Map<String, Integer> maps = new HashMap();
maps.put("nike", 3);
maps.put("java", 1);
maps.put("java", 100);
System.out.println(maps);
Set<String> keys = maps.keySet();
for (String key : keys) {
int value = maps.get(key);
System.out.println(key + "--->" + value);
}
}
}
- 键值对
package demo9;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test02 {
public static void main(String[] args) {
Map<String, Integer> maps = new HashMap<>();
maps.put("张三", 2);
maps.put("李四", 3);
maps.put("王五", 4);
System.out.println(maps);
Set<Map.Entry<String, Integer>> entries = maps.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
String key = entry.getKey();
int value = entry.getValue();
System.out.println(key + "--->" + value);
}
}
}
- Lambdar
package demo9;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
public class Test02 {
public static void main(String[] args) {
Map<String, Integer> maps = new HashMap<>();
maps.put("张三", 2);
maps.put("李四", 3);
maps.put("王五", 4);
System.out.println(maps);
maps.forEach(new BiConsumer<String, Integer>() {
@Override
public void accept(String key, Integer value) {
System.out.println(key + "--->" + value);
}
});
}
}
集合嵌套
package demo9;
import java.util.*;
public class MapTest {
public static void main(String[] args) {
Map<String, List<String>> data = new HashMap<>();
List<String> selects = new ArrayList<>();
Collections.addAll(selects, "A", "C");
data.put("张三", selects);
List<String> selects1 = new ArrayList<>();
Collections.addAll(selects1, "B", "C", "D");
data.put("李四", selects1);
List<String> selects2 = new ArrayList<>();
Collections.addAll(selects2, "A", "B", "C", "D");
data.put("王五", selects2);
System.out.println(data);
Map<String, Integer> infos = new HashMap<>();
Collection<List<String>> values = data.values();
for (List<String> value : values) {
for (String s : value) {
if (infos.containsKey(s)) {
infos.put(s, infos.get(s) + 1);
} else {
infos.put(s, 1);
}
}
}
System.out.println(infos);
}
}
不可变集合
package demo9;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Test03 {
public static void main(String[] args) {
List<Double> lists = List.of(50.1, 99.3, 89.8);
lists.set(2, 77.9);
System.out.println(lists);
Set<String> name = Set.of("张三", "李四", "王五");
name.add("刘二麻子");
System.out.println(name);
Map<String, Integer> maps = Map.of("huawei", 2, "apple", 3);
maps.put("xiaomi", 6);
System.out.println(maps);
}
}