单列集合
集合框架
Collection接口的使用
-
概述:单列集合的顶级接口
-
使用:
- 创建:Collection 对象名 = new 实现类对象()
- :泛型,决定了集合中能存储什么类型的数据,可以统一数据类型
- 泛型中只能写引用数据类型,如果不写,默认Object类型,此时什么类型的数据都可以存储
-
泛型细节:我们等号前面的泛型必须写,等号后面的泛型可以不写,jvm会根据前面的泛型推导出后面的泛型是什么
-
常用方法:
javaboolean add(E e):将给定的元素添加到当前集合中,返回的是Boolean类型 boolean addAll(Collection<? extends E> c):将另一个集合元素添加到当前集合中(集合合并) void clear():清除集合中的所有元素 boolean contains(Object o):判断当前集合中是否包含指定元素 boolean isEmpty():判断当前集合中是否为空 boolean remove(Object o):将指定的元素从集合中删除 int size():返回集合中的元素个数 Object[] toArray():把集合中的元素,存储到数组当中
List接口
-
概述:是Collection接口的子接口
-
常见的实现类:
ArrayList、 LinkedList 、Vector
ArrayList集合
-
概述:ArrayList是List接口的实现类
-
特点:
元素有序 -> 按照什么顺序存的就按照什么顺序取
元素可重复
有索引 -> 可以利用索引去操作元素
线程不安全
-
数据结构:数组
-
常用方法:
javaboolean add(E e) -> 将元素添加到集合当中,尾部添加 void add(int index, E element) -> 在指定索引位置添加元素 boolean remove (Objrct o) -> 删除指定的元素 E remove(int index) -> 删除指定索引位置上的元素,返回的是被删除的元素 E set(int index, E element) -> 将指定索引位置上的元素,修改成后面的element元素 E get(int index) -> 根据索引获取元素 int size() -> 获取集合元素个数
-
集合的遍历
java
import java.util.*;
public class hhh {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("=================");
for (String s : list) {
System.out.println(s);
}
System.out.println("=================");
//遍历带有索引的快捷键:集合名.fori
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
ArrayList构造方法:
ArrayList() 构造一个初始容量为10的空列表
ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表
注意:
不是一new底层就会创建一个初始容量为10的空列表,而是第一次add的时候
ArrayList底层会自动扩容 -> Arrays.copyOf -> 扩容1.5倍
LinkedList集合
-
概述:LinkedList是List接口的实现类
-
特点:
元素有序
元素可重复
有索引 -> 这里有索引指的是有操作索引的方法,不代表本质上有索引
线程不安全
-
数据结构:双向链表
-
方法:有大量直接操作首尾元素的方法
javapublic void addFirst(E e) -> 将指定元素插入此链表的开头 public E removeFirst() -> 删除并返回此链表的第一个元素 public void addLast(E e) -> public E removeLast() -> public E getFirst() -> 返回此列表的第一个元素 public E getLast() -> public E pop() -> 从此列表的堆栈中弹出一个元素,第一个 public void push(E e) -> 将元素推入此列表所表示的堆栈,第一个 public void isEmpty(E e) -> 判断列表是否为空
-
LinkedList底层成员解释说明
- LinkedKList底层成员
transient int size = 0;元素个数
transient Node first;第一个节点对象
transient Node last;最后一个结点对象 - Node代表的是节点对象
- LinkedKList底层成员
Vector集合
-
概述:Vector是List的实现接口
-
特点:
元素有序
有索引
元素可重复
线程安全
-
数据结构:数组
-
如果空参创造对象,数组初始容量为10,如果超出范围,自动扩容2倍
如果有参创造对象,如果超出了范围,自动扩容,扩的是老数组长度 + 指定容量的增量
java
import java.util.Vector;
public class HashTable {
public static void main(String[] args) {
Vector<String> strings = new Vector<>();
strings.add("aa");
strings.add("bb");
for (String string : strings) {
System.out.println(string)
}
}
}
Collections集合工具类
-
概述:集合工具类
-
特点:
构造私有
方法都是静态的
-
类名直接调用
-
常用方法与示例
java
import java.util.*;
public class hhh {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
//static <T> boolean addAll(Collection<? super T>c, T...element) -> 批量添加元素
Collections.addAll(list, "a", "e", "c", "d", "f", "g", "h");
System.out.println(list);
//static void shuffle(List<?> list) -> 将集合中的元素顺序打乱
Collections.shuffle(list);
System.out.println(list);
//static <T> void sort(List<T> list) -> 将集合中的元素进行排序--> ASCII码表
Collections.sort(list);
System.out.println(list);
}
}
- 元素按指定规则排序
java
static <T> void sort(List<T> list, Comparator<? super T> c) -> 将集合的元素按照指定规则排序
- Comparator比较器
java
2. 方法:
int compare(T o1, T o2)
o1-o2 -> 升序
o2-o1 -> 降序
public class student {
private String name;
private int age;
public student() {
}
public student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "student [name=" + name + ", age=" + age + "]";
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class studentTest {
public static void main(String[] args) {
ArrayList<student> stu = new ArrayList<>();
stu.add(new student("zz",24));
stu.add(new student("pp",29));
stu.add(new student("qq",26));
// Collections.sort(stu);//报错,里面三个对象,不知道按照什么排序
Collections.sort(stu,new Comparator<student>() {
@Override
public int compare(student o1, student o2) {
return o1.getAge()-(o2.getAge());
}
});
System.out.println(stu);
}
}
输出
[student [name=zz, age=24], student [name=qq, age=26], student [name=pp, age=29]]
- 接口:Comparable接口
java
方法:
int compareTo(T o) -> this-o(升序) o-this(降序)
public class student implements Comparable<student>{
private String name;
private Integer score;
public student(String name, Integer score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public String toString() {
return "name: " + name + ", score: " + score;
}
@Override
public int compareTo(student student) {
return this.getScore() - student.getScore();
//return this.score.compareTo(student.score);
}
}
import java.util.ArrayList;
import java.util.Collections;
public class studentTest {
public static void main(String[] args) {
ArrayList<student> students = new ArrayList<>();
students.add(new student("pp",23));
students.add(new student("py",24));
students.add(new student("pt",28));
students.add(new student("pg",26));
System.out.println(students);
Collections.sort(students);//已经知道怎么排列,因此不报错
System.out.println(students);
}
}
输出
[name: pp, score: 23, name: py, score: 24, name: pt, score: 28, name: pg, score: 26]
[name: pp, score: 23, name: py, score: 24, name: pg, score: 26, name: pt, score: 28]
- 拓展方法:Arrays中的静态方法
java
static <T> List<T> asList(T...a) -> 指定元素转存到list集合中
import java.util.Arrays;
import java.util.List;
class erweishuzu {
public static void main(String[] args) {
List<String> list = Arrays.asList("整数", "天天", "哈哈", "密码");
System.out.println(list);//[整数, 天天, 哈哈, 密码]
}
}
泛型
-
泛型<>
-
作用:统一数据类型,防止将来的数据转换异常
-
注意:
泛型中的类型必须是引用数据类型
如果泛型不写,默认类型为Object
为什么使用泛型
- 从使用层面来说:统一数据类型,防止将来的数据类型转换异常
java
import java.util.ArrayList;
class erweishuzu {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("1");
list.add(2);
list.add("abc");
list.add(true);
for(Object o : list){
String s = (String) o;
System.out.println(s.length()); //从第二个开始报错
}
}
}
- 从定义层面来看:定义带泛型的类、方法等,将来使用的时候给泛型确定什么类型,泛型就会变成什么类型,凡是涉及到泛型的都会变成确定的类型,代码更灵活
泛型的定义
- 含有泛型的类
java
1.定义:
public class 类名<E>{
}
2.什么时候确定类型:new对象的时候确定类型
import java.util.Arrays;
public class erweishuzu <E>{
Object[] obj = new Object[10];
int size;
public boolean add(E e){
obj[size] = e;
size++;
return true;
}
public E get(int index){
return (E)obj[index];
}
@Override
public String toString() {
return Arrays.toString(obj);
}
}
public class ptakaoshi {
public static void main(String[] args) {
erweishuzu<String> objecterweishuzu = new erweishuzu<>();
objecterweishuzu.add("aaa");
objecterweishuzu.add("bbb");
System.out.println(objecterweishuzu); //[aaa, bbb, null, null, null, null, null, null, null, null]
erweishuzu<Integer> objecterweishuzu1 = new erweishuzu<>();
objecterweishuzu1.add(1);
objecterweishuzu1.add(2);
objecterweishuzu1.add(3);
System.out.println(objecterweishuzu1); //[1, 2, 3, null, null, null, null, null, null, null]
Integer ele = objecterweishuzu1.get(0);
System.out.println(ele); //1
}
}
- 含有泛型的方法
java
1.格式:
修饰符 <E> 返回值类型 方法名(E e)
2.什么时候确定类型:调用的时候确定类型
import java.util.ArrayList;
public class erweishuzu <E>{
public static <E> void addAll(ArrayList<E> list,E...e){
for(E e1 : e){
list.add(e1);
}
}
}
import java.util.ArrayList;
public class ptakaoshi {
public static void main(String[] args) {
ArrayList<String> objects = new ArrayList<>();
erweishuzu.addAll(objects,"a","b","c","d","e","f","g","h","i");
System.out.println(objects); //[a, b, c, d, e, f, g, h, i]
ArrayList<Integer> list2 = new ArrayList<>();
erweishuzu.addAll(list2,1,2,3,4,5,6,7,8,9);
System.out.println(list2); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
}
}
- 含有泛型的接口
java
1.格式:
public interface 接口名<E>{
}
2.什么时候确定类型:
在实现类的时候还没有确定类型,只能在new实现类的时候确定类型了 -> 比如:ArrayList
在实现类的时候直接确定类型了 -> 比如Scanner
java
public interface Mylist <E>{
public boolean add(E e);
}
import java.util.Arrays;
public class Mylist1 <E> implements Mylist<E> {
Object[] obj = new Object[10];
int size = 0;
public boolean add(E e) {
obj[size] = e;
size++;
return true;
}
public E get(int index) {
return (E) obj[index];
}
public String toString(){
return Arrays.toString(obj);
}
}
public class Text1 {
public static void main(String[] args) {
Mylist1<String> list1 = new Mylist1<>();
list1.add("An");
list1.add("Bn");
System.out.println(list1);//[An, Bn, null, null, null, null, null, null, null, null]
}
}
java
public interface MySca <E>{
E next();
}
public class Myscann implements MySca <String>{
@Override
public String next() {
return "hhh";
}
}
public class Text2 {
public static void main(String[] args) {
Myscann myscann = new Myscann();
String result = myscann.next();
System.out.println(result); //hhh
}
}
泛型的高级使用
- 泛型通配符
java
import java.util.*;
public class hhh {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
list1.add("a");
list1.add("b");
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(1);
list2.add(2);
method(list1);
method(list2);
}
public static void method(ArrayList<?> list) {
for(Object o : list) {
System.out.println(o);
}
}
}
- 泛型的上限下限
java
1.作用:可以规定泛型的范围
2.上限:
格式:<? extends 类型>
含义:?只能接收extends后面的本类类型以及子类类型
3.下限:
格式:<? super 类型>
含义:?只能接收super后面的本类类型以及父类类型
应用场景:
- 如果我们在定义类、方法、接口的时候,如果类型不确定,我们可以考虑定义含有泛型的类、方法、接口
- 如果类型不确定,但是能知道以后只能传递某个类的继承体系中的子类或者父类,就可以使用泛型的通配符
Set集合
Set接口属于Collection接口的另外一个子接口,并没有对Collection进行任何功能上的扩充,而且所有的set集合底层都是依靠Map实现的
Set集合介绍
- Set和Map密切相关
- Map的遍历要先变成单列集合,只能变成Set集合
HashSet集合的介绍和使用
-
概述:HashSet是Set接口的实现类
-
特点:
元素唯一
元素无序
无索引
线程不安全
-
数据结构:哈希表
jdk8之前:哈希表 = 数组 + 链表
jdk8之后:哈希表 = 数组 + 链表 + 红黑树(加入红黑树是为了查询快)
-
方法:和collection一样
-
遍历:增强for、迭代器
java
import java.util.HashSet;
import java.util.Iterator;
public class koko1 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("一样");
set.add("会将");
set.add("雨哦");
System.out.println(set);
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
for (String s : set) {
System.out.println(s);
}
}
}
LinkedHashSet集合的介绍和使用
-
概述:LinkedHashSet继承HashSet
-
特点:
元素唯一
元素有序
无索引
线程不安全
-
数据结构:哈希表 + 双向链表
-
使用:与父类一样
java
import java.util.Iterator;
import java.util.LinkedHashSet;
public class koko1 {
public static void main(String[] args) {
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("一样");
set.add("会将");
set.add("雨哦");
System.out.println(set);
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
for (String s : set) {
System.out.println(s);
}
}
}
TreeSet
-
概述:TreeSet是set的实现类
-
特点:
对元素进行排序
无索引
不能存null
线程不安全
元素唯一
-
数据结构:红黑树
java
构造:
TreeSet() -> 构造一个新的空树集,根据其元素的自然顺序进行排序。-> ASCII
TreeSet(Comparator<? super E> comparator) -> 构造一个新的空树集,根据指定的比较器排序。
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" + "name=" + name + ", age=" + age + '}';
}
}
import java.util.Comparator;
import java.util.TreeSet;
public class PersonText {
public static void main(String[] args) {
TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-(o2.getAge());
}
});
persons.add(new Person("hh",16));
persons.add(new Person("jj",19));
persons.add(new Person("gg",12));
System.out.println(persons);
//[Person{name=gg, age=12}, Person{name=hh, age=16}, Person{name=jj, age=19}]
}
}
哈希值
-
概述:是由计算机计算出来的一个十进制数,可以看作是对象的地址值
-
获取对象的哈希值,使用的是Object中的方法
javapublic native int HashCode()
-
如果重写了hashCode方法,那计算的就是对象内容的哈希值了
- 哈希值不一样,内容肯定不一样
- 哈希值一样,内容也有可能不一样
集合遍历方式
迭代器
基本使用
-
概述:Iterator接口
-
主要作用:遍历集合
-
获取:Collection中的方法:
javaIterator<E> iterator()
-
方法:
javaboolean hasNext() -> 判断集合中有没有下一个元素 E next() -> 获取下一个元素
java
import java.util.ArrayList;
import java.util.Iterator;
public class dieDai1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
//获取迭代器对象
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());//A B C D
}
}
}
迭代过程
java
int cursor; //下一个元素索引位置
int lastRet = -1; //上一个元素索引位置
底层原理
java
1.获取Iterator的时候怎么获取的:
Iterator iterator = list.iterator()
Iterator是一个接口,等号右边是他的实现类对象,接收的是ArrayList中的内部类Itr对象
注意:只有ArrayList使用迭代器的时候iterator接口才会指向Itr,其他的就不指向了
并发修改异常
java
import java.util.ArrayList;
import java.util.Iterator;
public class A1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
if("C".equals(s)){
list.add("e");
}
}
System.out.println(list);
}
}
输出报错:
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1096)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1050)
at PPPttt.A1.main(A1.java:15)
迭代器内部维护了一个expectedModificationCount
,即预期的操作次数,当集合的实际修改次数与这个计数不匹配时(当预期操作次数和实际操作次数不相等了),就会抛出ConcurrentModificationException
(并发修改异常)
使用迭代器迭代集合的过程中,不要随意修改集合长度,容易出现并发修改异常
补充
ArratList中的方法:ListIterator listIterator
在Java中,ListIterator<E>
是 Iterator<E>
接口的一个扩展,专门为 List
接口的实现类提供额外的操作。ListIterator
允许程序员对列表进行双向迭代,即既可以向前迭代也可以向后迭代,这与只能单向迭代的普通 Iterator
不同。
ArrayList
类实现了 List
接口,因此它提供了 listIterator()
方法来创建和返回一个 ListIterator
对象。
- ListIterator 的特点:
- 双向迭代 :
ListIterator
可以调用next()
方法来获取下一个元素,也可以调用previous()
方法来获取上一个元素。 - 修改列表 :
ListIterator
允许在迭代过程中修改列表(通过add(E e)
和set(E e)
方法)。 - 获取当前位置 :
ListIterator
提供了nextIndex()
和previousIndex()
方法来获取当前迭代位置的索引。 - 检查可迭代方向 :
hasNext()
和hasPrevious()
方法用来检查迭代器是否有下一个或上一个元素。
- ListIterator 的基本操作:
add(E e)
: 在next()
或previous()
调用之后,可以在列表中的当前位置插入一个元素。hasNext()
: 如果迭代器有更多元素进行正向遍历,则返回true
。next()
: 返回迭代器中的下一个元素并前进。hasPrevious()
: 如果迭代器有更多元素进行反向遍历,则返回true
。previous()
: 返回迭代器中的上一个元素并后退。set(E e)
: 用指定的元素替换最后一次由next()
或previous()
返回的元素。nextIndex()
: 返回下一个调用next()
方法时返回的元素的索引。previousIndex()
: 返回下一个调用previous()
方法时返回的元素的索引。
增强for
-
基本使用
- 作用:遍历集合或者数组
- 格式:
for(元素类型 变量名:要遍历的集合名或者数组名){
变量名就是代表的每一个元素
} - 快捷键:集合名或者数组名.for
javaimport java.util.ArrayList; public class LinkList { public static void main(String[] args) { ArrayList<String> s = new ArrayList<>(); s.add("a"); s.add("b"); s.add("c"); for (String st : s) { System.out.println(st); } int[] a = {1,2,3,4,5}; for(int i : a){ System.out.println(i); } } }
-
注意
java1.增强for遍历集合时,底层实现原理为迭代器 2.增强for遍历数组时,底层实现原理为普通for
所以不管是用迭代器还是使用增强for,在遍历集合的过程中都不要随意修改集合长度,否则会出现并发修改异常
双列集合
HashMap
HashMap的介绍和使用
-
概述:HashMap是Map的实现类
-
特点:
key唯一,value可重复 -> 如果key重复了,会发生value覆盖
无序
无索引
线程不安全
可以存null键null值
-
数据结构:哈希表
-
常用方法:
javaV put(K key, V value) -> 添加元素,返回的是被覆盖的value V remove(Object key) -> 根据key删除键值对,返回的是被删除的value V get(Object key) -> 根据key获取value boolean containsKey(Object key) -> 判断集合中是否包含指定的key 判断集合中是否包含指定的value boolean v5 = map.containsValue("d"); Collection<V> values() -> 获取集合中所有的value,转存到Collection集合中
LinkedHashMap
- 概述:LinkedHashMap extends HashMap
- 特点:
key唯一,value可重复 -> 如果key重复了,会发生value覆盖
有序
无索引
线程不安全
可以存null键null值 - 数据结构:哈希表 + 双向链表
- 使用:和HashMap一样
HashMap的两种遍历方式
-
获取key,根据key再获取value
javaSet<K> KeySet() -> 将Map中的Key获取出来,转存到Set集合中
Javaimport java.util.LinkedHashMap; import java.util.Set; public class HashMap1 { public static void main(String[] args) { LinkedHashMap<String, String> map = new LinkedHashMap<>(); map.put("a", "b"); map.put("c", "d"); Set<String> keySet = map.keySet(); for (String key : keySet) { String value = map.get(key); System.out.println(key + "=" + value); } } }
-
同时获取key和value
javaSet<Map,Entry<K,V>> entrySet() -> 获取Map集合中的键值对,转存到Set集合中
javaimport java.util.*; public class HashMap1 { public static void main(String[] args) { LinkedHashMap<String, String> map = new LinkedHashMap<>(); map.put("a", "b"); map.put("c", "d"); map.put("k", "l"); Set<Map.Entry<String, String>> entries = map.entrySet(); for (Map.Entry<String, String> entry : entries) { System.out.println(entry.getKey() + " = " + entry.getValue()); } } }
Map存储自定义对象时如何去重复
java
import java.util.Objects;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
import java.util.HashMap;
public class PersonText {
public static void main(String[] args) {
HashMap<Person,String> map = new HashMap<>();
map.put(new Person("哈哈",18),"渭南");
map.put(new Person("天天",16),"西安");
map.put(new Person("解决",15),"重庆");
map.put(new Person("哈哈",18),"北京");
System.out.println(map);
}
}
如果key为自定义类型,去重复的话,重写hashCode和equals方法,去重复过程和set一样,因为set集合的元素到了底层都是保存到了map和key位置上
TreeMap
- 概述:TreeMap是Map的实现类
- 特点:
对key进行排序
无索引
不能存null
线程不安全
key唯一 - 数据结构:红黑树
java
TreeMap() -> 使用其键的自然顺序构造一个新的空树图。
TreeMap(Comparator<? super K> comparator) -> 构造一个新的空树图,根据给定的比较器排序。
import java.util.Comparator;
import java.util.TreeMap;
public class PersonText {
public static void main(String[] args) {
TreeMap<Person,String> map = new TreeMap(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-(o2.getAge());
}
});
map.put(new Person("hh",16),"a");
map.put(new Person("jj",19),"k");
map.put(new Person("gg",12),"c");
System.out.println(map);
//[Person{name=gg, age=12}, Person{name=hh, age=16}, Person{name=jj, age=19}]
}
}
Hashtable集合
-
概述:Hashtable是Map的实现类
-
特点:
key唯一,value可重复 -> 如果key重复了,会发生value覆盖
无序
无索引
线程不安全
不可以存null键null值
-
数据结构:哈希表
java
import java.util.Hashtable;
public class HashTable {
public static void main(String[] args) {
Hashtable<String, String> ht = new Hashtable<String, String>();
ht.put("a", "b");
ht.put("c", "d");
ht.put("e", "f");
ht.put("c", "h");
// ht.put(null,null);//报错
System.out.println(ht); //{a=b, e=f, c=h}
}
}
HashMap和Hashtable区别:
-
相同点:元素无序、无索引、key唯一
-
不同点:HashMap线程不安全,Hashtable线程安全
HashMap可以存储null键null值,Hashtable不可以
Properties集合
-
概述:Properties继承Hashtable
-
特点:
key唯一,value可重复 -> 如果key重复了,会发生value覆盖
无序
无索引
线程不安全
不可以存null键null值
Properties的key与value默认为String
-
数据结构:哈希表
-
常用方法:
javaObject setProperty(String key, String value) -> 存键值对 String getProperty(String key) -> 根据key获取value Set<String> stringPropertyNames() -> 获取所有的key,保存到set集合中,相当于keySet方法 void load(InputStream inStream) -> 从输入字节流中读取属性列表(键和元素对)
无序 无索引 线程不安全 不可以存null键null值
-
数据结构:哈希表
java
import java.util.Hashtable;
public class HashTable {
public static void main(String[] args) {
Hashtable<String, String> ht = new Hashtable<String, String>();
ht.put("a", "b");
ht.put("c", "d");
ht.put("e", "f");
ht.put("c", "h");
// ht.put(null,null);//报错
System.out.println(ht); //{a=b, e=f, c=h}
}
}
HashMap和Hashtable区别:
-
相同点:元素无序、无索引、key唯一
-
不同点:HashMap线程不安全,Hashtable线程安全
HashMap可以存储null键null值,Hashtable不可以
Properties集合
-
概述:Properties继承Hashtable
-
特点:
key唯一,value可重复 -> 如果key重复了,会发生value覆盖
无序
无索引
线程不安全
不可以存null键null值
Properties的key与value默认为String
-
数据结构:哈希表
-
常用方法:
javaObject setProperty(String key, String value) -> 存键值对 String getProperty(String key) -> 根据key获取value Set<String> stringPropertyNames() -> 获取所有的key,保存到set集合中,相当于keySet方法 void load(InputStream inStream) -> 从输入字节流中读取属性列表(键和元素对)
总结
- List接口:
- ArrayList:基于动态数组实现,适用于随机访问。插入和删除元素时可能需要数组复制,因此较慢。
- LinkedList:基于双向链表实现,适用于频繁的插入和删除操作。但是,随机访问速度较慢。
- Vector:类似于ArrayList,但它是同步的。由于性能问题,通常不推荐使用。
- 选择:当需要频繁随机访问元素时,选择ArrayList。当需要频繁在列表中间插入或删除元素时,选择LinkedList。
- Set接口:
- HashSet:基于HashMap实现,无序,允许null元素,查找速度快。
- LinkedHashSet:类似于HashSet,但维护元素的插入顺序。
- TreeSet:基于NavigableMap实现,可以按照自然顺序或自定义顺序对元素进行排序。
- 选择:当需要快速查找元素且不需要元素有序时,选择HashSet。当需要维护元素插入顺序时,选择LinkedHashSet。当需要有序集合时,选择TreeSet。
- Map接口:
- HashMap:基于散列表实现,键值对映射,无序,允许一个null键和多个null值。
- LinkedHashMap:类似于HashMap,但维护键值对的插入顺序。
- TreeMap:基于红黑树实现,可以按照自然顺序或自定义顺序对键进行排序。
- Hashtable:类似于HashMap,但它是同步的。由于性能问题,通常不推荐使用。
- 选择:当需要快速查找键值对且不需要键有序时,选择HashMap。当需要维护键值对的插入顺序时,选择LinkedHashMap。当需要有序的键值对映射时,选择TreeMap。