数据结构
栈
先进后出
【入口和出口在同一侧】
存储元素到集合:入、压栈
取出集合中的元素:出、弹栈
队列
先进先出
【入口和出口在集合的两侧】
数组
查询快,增删慢
【数组的地址是连续的,通过数组的首地址可以找到数组,通过数组的索引可以快速查找某一个元素】
【数组的长度是固定的,想要增加/删除一个元素,必须创建一个新数组,把源数组的数据复制过来】
链表
查询慢,增删快
【链表中地址不是连续的,每次查询元素必须从头查询】
【链表结构增加/删除一个元素,对链表的整体结构没有影响,所以增删快】
链表中的每一个元素也称之为一个节点。
一个节点包含了一个数据源(存储数据),两个指针域(存储地址)。【自己的地址 | 数据 | 下一个节点的地址】
单向链表: 链表中只有一条链子,不能保证元素的顺序(存储元素和取出元素的顺序可能不一致)。
双向链表: 链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合。
红黑树
二叉树:分支不能超过两个。
排序树/查找树:在二叉树的基础上,元素是有大小顺序的。(左子树小,右子树大)
平衡树:左孩子和右孩子相等。
不平衡树:左孩子不等于右孩子。
红黑树: 特点趋近于平衡树,查询速度非常快,查询叶子节点最大次数不能超过最小次数的二倍。
【节点可以是红色的或黑色的】
【根节点是黑色的】
【叶子节点(空节点)是黑色的】
【每个红色的节点的子节点都是黑色的】
【任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同】
List集合
java.util.List extends Collection
List接口的特点:
1.有序的集合,存储元素和取出元素的顺序是一致的。
2.有索引,包含一些带索引的方法。
3.允许存储重复的元素。
List接口中带索引的方法(特有):
操作索引时要注意索引越界异常
【IndexOutOfBoundsException】索引越界异常,集合会报
【ArrayIndexOutOfBoundsException】数组越界异常
【StringIndexOutOfBoundsException】字符串越界异常
1. public void add(int index,E element)
【将指定的元素添加到该给集合中指定的位置上】
2. public E get(int index)
【返回集合中指定位置的元素】
3. public E remove(int index)
【移除列表中指定位置的元素,返回移除的元素】
4. public E set(int index,E element)
【用指定元素替换集合中指定位置的元素,返回更新前的元素】
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Demo01List {
public static void main(String[] args) {
//创建一个List集合对象,使用多态
List<String> list = new ArrayList<String>();
//使用add方法添加元素
list.add("1");
list.add("2");
list.add("3");
list.add("4");
//打印list
System.out.println(list);//[1, 2, 3, 4] 重写了toString方法
//public void add(int index,E element)
list.add(2, "a");
//打印list
System.out.println(list);//[1, 2, a, 3, 4]
//public E get(int index)
String s1 = list.get(2);
System.out.println(s1);//a
System.out.println(list);//[1, 2, a, 3, 4]
//public E remove(int index)
String s2 = list.remove(2);
System.out.println(s2);//a
System.out.println(list);//[1, 2, 3, 4]
//public E set(int index,E element)
String s3 = list.set(2, "A");
System.out.println(s3);//3
System.out.println(list);//[1, 2, A, 4]
//List 集合有三种遍历方式
//普通for循环
for(int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.print(s);//12A4
}
System.out.println();
//迭代器
Iterator<String> it = list.iterator();
while(it.hasNext()) {
String s = it.next();
System.out.print(s);//12A4
}
System.out.println();
//增强for循环
for(String s : list) {
System.out.print(s);//12A4
}
}
}
ArrayList集合
java.util.ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快。
LinkedList集合
java.util.Linked集合 implements List接口
特点:
1.底层是一个链表结构:查询慢,增删快。
2.里面包含了大量操作首尾元素的方法。
【使用LinkedList集合特有方法不能使用多态】
1. public void addFirst(E e)
【将指定元素插入该列表的开头】
2. public void addLast(E e)
【等效于add方法】
【将指定元素添加到该列表的末尾】
3. public E getFirst()
【返回此列表的第一个元素】
4. public E getLast()
【返回此列表的最后一个元素】
5. public E removeFirst()
【相当于E remove()方法】
【移除并返回此列表的第一个元素】
6. public E removeLast()
【移除并返回此列表的最后一个元素】
7. public E pop()
【相当于removeFirst()方法】
【从此列表所表示的堆栈出弹出一个元素】
8. public void push(E e)
【等效于addFirst(E)】
【将元素推入此列表所表示的堆栈】
9. public boolean isEmpty()
【如果列表不包含元素,返回true】
import java.util.LinkedList;
public class Demo02LinkedList {
public static void main(String[] args) {
// method1();
// method2();
method3();
}
private static void method3() {
//创建LinkedList对象
LinkedList<String> linked = new LinkedList<>();
//添加元素
linked.add("a");
linked.add("b");
linked.add("c");
//E removeFirst 等价 E pop 等价 E remove() E removeLast
// String first = linked.removeFirst();
// String first = linked.remove();
String first = linked.pop();
System.out.println(first);//a
String last = linked.removeLast();
System.out.println(last);//c
System.out.println(linked);//[b]
}
private static void method2() {
//创建LinkedList对象
LinkedList<String> linked = new LinkedList<>();
//添加元素
linked.add("a");
linked.add("b");
linked.add("c");
//E getFirst E getLast boolean isEmpty
if(! linked.isEmpty()) {
String first = linked.getFirst();
System.out.println(first);//a
String last = linked.getLast();
System.out.println(last);//c
}
}
private static void method1() {
//创建LinkedList对象
LinkedList<String> linked = new LinkedList<String>();
//添加元素
linked.add("a");
linked.add("b");
linked.add("c");
//void addFirst 等价 void push void addLast
linked.addFirst("A");
System.out.println(linked);//[A, a, b, c]
linked.addLast("C");
System.out.println(linked);//[A, a, b, c, C]
linked.push("A");
System.out.println(linked);//[A, A, a, b, c, C]
}
}
Vector集合(了解)
底层是数组,是同步的(单线程)
Set接口
java.util.Set接口 extends Collection接口
特点:
1.不允许存储重复的元素。
2.没有索引,没有带索引的方法,不能使用普通的for循环遍历。
HashSet集合
java.util.HashSet集合 implements set接口
特点:
1.不允许存储重复的元素。
2.没有索引,没有带索引的方法,不能使用普通的for循环遍历。
3.是一个无序的集合,存储和取出元素的顺序可能不一致。
4.底层是一个哈希表结构(速度非常快)。
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo03Set {
public static void main(String[] args) {
//创建一个Set对象
Set<Integer> set = new HashSet<Integer>();
//添加元素
set.add(1);
set.add(2);
set.add(1);
set.add(4);
System.out.println(set);//[1, 2, 4] 重写了toString方法
//遍历set
//使用迭代器遍历
Iterator<Integer> it = set.iterator();
while(it.hasNext()) {
int i = it.next();
System.out.print(i);//124
}
System.out.println();
//使用增强for遍历
for(int i : set) {
System.out.print(i);//124
}
}
}
HashSet集合存储数据的结构(哈希表)
哈希值: 是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址)
在Object类有一个方法,可以获取对象的哈希值
int hashCode()
【返回该对象的哈希码值】
hashCode方法的源码:
public native int hashCode()
【native代表该方法调用的是本地操作系统的方法】
哈希表
jdk1.8之前 :
哈希表=数组+链表
jdk1.8之后 :
哈希表=数组+链表
哈希表=数组+红黑树(提高查询的速度)
哈希表的特点:速度快
Set存储元素不重复的原理
前提: 存储的元素必须重写hashCode方法和equals方法
Set集合在调用add方法时,add方法会调用元素的hashCode方法和equals方法,判断元素是否重复。
当哈希值相同且equals方法返回true时,将元素存入集合。
HashSet存储自定义类型元素
给HashSet中存放自定义类型元素时,需要重写对象中的hashcode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一
/*
* 同年龄同名视为同一人,只能存储一次
*/
import java.util.HashSet;
public class Demo04HashSetSavePerson {
public static void main(String[] args) {
//创建HashSet集合存储Person对象
HashSet<Person> set = new HashSet<>();
Person p1 = new Person("周老大",3);
Person p2 = new Person("周老二",2);
Person p3 = new Person("周老二",2);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set);//[Person [name=周老大, age=3], Person [name=周老二, age=2]]
}
}
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
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;
Person other = (Person) 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;
}
@Override
public String toString() {
return "Person [name=" + name + ", 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;
}
}
LinkedHashSet集合
java.util.HashSet集合 extends HashSet集合 implements Set集合
特点:
底层是一个哈希表(数组+链表/红红黑树)+链表(记录元素的存储顺序),保证元素有序。
import java.util.HashSet;
import java.util.LinkedHashSet;
public class Demo05LinkedHashSet {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("a");
set.add("c");
set.add("b");
set.add("a");
System.out.println(set);//[a, b, c]
LinkedHashSet<String> linked = new LinkedHashSet<>();
linked.add("a");
linked.add("c");
linked.add("b");
linked.add("a");
System.out.println(linked);//[a, c, b]
}
}
可变参数
可变参数是java1.5之后出现的新特性。
使用前提 :
当方法的参数列表的数据类型已经确定,但参数的个数不确定,就可以使用可变参数。
使用格式:
定义方法时使用
修饰符 返回值类型 方法名(数据类型...参数名称){}
可变参数的原理:
可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数。
传递的参数个数可以是任意多个也可以不传递(0个)。
public class Demo01varArgs {
public static void main(String[] args) {
add();
}
//add():就会创建一个长度为0的数组。int[] arr = {}; 传几个参数创建的数组长度就为几。
public static int add(int...arr) {
System.out.println(arr);//[I@60f82f98 底层是一个数组
System.out.println(arr.length);//0
return 0;
}
}
注意:
1.一个方法的参数列表只能有一个可变参数。
2.如果方法的参数有多个,那么可变参数必须写在参数列表的末尾。
可变参数的特殊(终极)写法
public static void method(Object...obj){}
public class Demo01varArgs {
public static void main(String[] args) {
int request = add(1,2,3,10,90);
System.out.println(request);
}
public static int add(int...arr) {
int sum = 0;
for(int i : arr) {
sum += i;
}
return sum;
}
}
Collections集合工具类
1. public static <T> boolean addAll(Collection<T> c,T...elements)
【往集合中添加一些元素】
2. public static void shuffle(List<?> list)
【打乱集合顺序】
3. public static <T> void sort(List<T> list)
【将集合中的元素按照默认规则排序(升序)】
【被排序的集合里面的元素必须实现Comparable,重写里面的CompareTo定义排序规则】
4. public static <T> void sort(List<T> list,Comparator<? super T>)
【将集合中元素按照指定规则排序】
Comparable和Comparator的区别:
Comparable: 自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较规则compareTo方法。
Comparator: 相当与找一个第三方裁判来比较。
import java.util.ArrayList;
import java.util.Collections;
public class Demo07Collections {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 1,2,3,4,5);
System.out.println(list);//[1, 2, 3, 4, 5]
Collections.shuffle(list);
System.out.println(list);//[4, 1, 3, 2, 5]
Collections.sort(list);
System.out.println(list);//[1, 2, 3, 4, 5]
ArrayList<People> list1 = new ArrayList<People>();
list1.add(new People("周老大",3));
list1.add(new People("周老三",1));
list1.add(new People("周老二",2));
Collections.sort(list1);
System.out.println(list1);
//[People [name=周老大, age=3], People [name=周老二, age=2], People [name=周老三, age=1]]
}
}
public class People implements Comparable<People>{
private String name;
private int age;
public People() {
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "People [name=" + name + ", 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(People o) {
// TODO Auto-generated method stub
// return 0;//认为元素都是相同的
// return o.getAge() - this.getAge();//按年龄降序排序
return this.getAge() - o.getAge();//按年龄升序排序
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Demo08Sort {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
Collections.addAll(list01,1,3,4,2,7,0);
System.out.println(list01);//[1, 3, 4, 2, 7, 0]
Collections.sort(list01, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o1 -o2;
}
});
System.out.println(list01);//[0, 1, 2, 3, 4, 7]
ArrayList<Student> list02 = new ArrayList<>();
list02.add(new Student("周老大",3));
list02.add(new Student("周老三",1));
list02.add(new Student("b周老二",2));
list02.add(new Student("a周老二",2));
System.out.println(list02);
//[Student [name=周老大, age=3], Student [name=周老三, age=1], Student [name=b周老二, age=2], Student [name=a周老二, age=2]]
Collections.sort(list02, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
// return o1.getAge()-o2.getAge();//升序
//如果两个人年龄一样就按姓名的第一个字排序
int result = o1.getAge() - o2.getAge();
if(result == 0) {
result = o1.getName().charAt(0) - o2.getName().charAt(0);
}
return result;
}
});
System.out.println(list02);
//[Student [name=周老三, age=1], Student [name=b周老二, age=2], Student [name=a周老二, age=2], Student [name=周老大, age=3]]
//[Student [name=周老三, age=1], Student [name=a周老二, age=2], Student [name=b周老二, age=2], Student [name=周老大, age=3]]
}
}
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", 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;
}
}
Map集合
java.util.Map<K,V>集合
Map集合的特点:
1.Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
2.Map集合中的元素,key和value的数据类型可以相同也可以不同
3.Map集合中的元素,key值是不允许重复的,value是可以重复的
4.Map集合中的元素,key和value是一一对应的
Map集合常用子类
java.util.HashMap<K,V>集合 implements Map<K,V>接口
HashMap集合的特点:
1.HashMap集合底层是哈希表:查询的速度特别快
JDK1.8之前:数组+单向链表
JDK1.8之后:数组+单向链表/红黑树(链表长度超过8):提高查询速度
2.HashMap集合是一个无序的集合,存储元素和取出元素的顺序可能不一致
java.util.LinkedHashMap<K,V>集合 extends HashMap<K,V>集合
LinkedHashMap集合的特点:
1.LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
2.LinkedHashMap集合是有序的,存储元素和取出元素的顺序是一致的
Map接口中常用的方法
1. public V put(K key,V valiue)
【把指定的键和指定的值添加到对应的Map集合中去】
【存储键值对的时候,K不重复,返回值是null】
【存储键值对的时候,K重复,会使用新的value替换Map中重复的value,返回被替换的value】
2. public V remove(Object key)
【把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值】
【key不存在时,返回null】
3. public V get(Object key)
【根据指定的键,在Map中获取对应的值】
【K不存在返回null】
4. boolean containsKey(Object key)
【判断集合中是否包含指定的键】
import java.util.HashMap;
import java.util.Map;
public class Demo09Map {
public static void main(String[] args) {
method1();//public V put(K key,V valiue)
method2();//public V remove(Object key)
method3();//public V get(Object key)
method4();//public boolean containsKey(Object key)
}
private static void method4() {
//boolean containsKey(Object key) 包含指定的键返回true,不包含返回false
//创建Map集合对象
Map<Integer,Double> map = new HashMap<>();
//向map中存储键值对
map.put(1,1.1);
map.put(2,1.2);
map.put(3,1.3);
System.out.println(map);//{1=1.1, 2=1.2, 3=1.3}
boolean b1 = map.containsKey(2);
System.out.println(b1);//true
System.out.println(map);//{1=1.1, 2=1.2, 3=1.3}
boolean b2 = map.containsKey(0);
System.out.println(b2);//false
}
private static void method3() {
//public V get(Object key) K不存在时返回null
//创建Map集合对象
Map<Integer,Double> map = new HashMap<>();
//向map中存储键值对
map.put(1,1.1);
map.put(2,1.2);
map.put(3,1.3);
System.out.println(map);//{1=1.1, 2=1.2, 3=1.3}
Double v1 = map.get(2);
System.out.println(v1);//1.2
System.out.println(map);//{1=1.1, 2=1.2, 3=1.3}
Double v2 = map.get(0);
System.out.println(v2);//null
System.out.println(map);//{1=1.1, 2=1.2, 3=1.3}
}
private static void method2() {
//public V remove(Object key) K不存在时返回null,存在则返回被删除value
//创建Map集合对象
Map<Integer,Integer> map = new HashMap<>();
//向map中存储键值对
map.put(1, 01);
map.put(2, 02);
map.put(3, 03);
System.out.println(map);//{1=1, 2=2, 3=3}
Integer value01 = map.remove(2);
System.out.println(value01);//2
System.out.println(map);//{1=1, 3=3}
// int value02 = map.remove(2);//NoPointException 空指针异常
Integer value02 = map.remove(2);
System.out.println(value02);//null
System.out.println(map);//{1=1, 3=3}
}
private static void method1() {
//public V put(K key,V valiue) K值不存在时返回null,存在时返回被替换的value
//创建Map集合对象
Map<Integer,String> map = new HashMap<>();
String value01 = map.put(1,"1");
System.out.println(value01);//null
System.out.println(map);//{1=1}
String value02 = map.put(1,"2");
System.out.println(value02);//1
System.out.println(map);//{1=2}
}
}
1. public Set<K> keySet()
【获取Map集合中所有的键,存储到Set集合中】
【通过键找值遍历Map集合】
2. public Set<Map.Entry<K,V>> entrySet()
【将Map集合中所有键值对对象(Entry对象)存储到Set集合】
Entry对象中的方法:
getKey()【获取key】
getValue()【获取value】
Map.Entry<K,V>: 在Map接口中有一个内部接口Entry
作用:当Map集合一创建,那么就会在Map集合中创建一个Entry对象,用来记录键与值(键值对对象,键与值的映射关系)
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
* Map 的第一种遍历方式,通过键找值
*/
public class Demo10MapKeySet {
public static void main(String[] args) {
Map<Integer,Integer> map = new HashMap<>();
map.put(1, 10);
map.put(3, 30);
map.put(2, 20);
System.out.println(map);
//使用Set<K> keySet获取Map中的所有键值存到Set中
Set<Integer> set = map.keySet();
System.out.println(set);//[1, 2, 3]
//遍历set获取map中的每一个key 使用迭代器或增强for循环
//使用Map中的get(K)通过key找到value
for(int key : set) {
Integer v = map.get(key);
System.out.println(v);
// 10
// 20
// 30
}
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/*
* Map 的第二种遍历方式,通过Map中的Entry对象遍历Map集合
*/
public class Demo11MapEntry {
public static void main(String[] args) {
//创建Map对象
Map<Integer,Integer> map = new HashMap<>();
map.put(1, 10);
map.put(3, 30);
map.put(2, 20);
//使用Map中的Set<Map.Entry<K,V>> entrySet()将Entry对象存储到中
Set<Entry<Integer, Integer>> set = map.entrySet();
//遍历set获得Entry对象 使用迭代器或增强for循环
//可以通过Entry的getKey和getValue获得key与value
Iterator<Entry<Integer, Integer>> it = set.iterator();
while(it.hasNext()) {
Entry<Integer, Integer> e = it.next();
System.out.println(e);//1=10 2=20 3=30
// Integer k = e.getKey();
// Integer v = e.getValue();
// System.out.println(k + "=" + v);//1=10 2=20 3=30
}
}
}
HashMap存储自定义类型键值
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo12HashMapSetPerson {
public static void main(String[] args) {
/*创建HashMap集合
* key:String,不能重复,已经重写了hashCode和equals方法
* value:Person,可以重复
*/
HashMap<String, Person> map1 = new HashMap<String, Person>();
map1.put("1", new Person("周老大",3));
map1.put("2", new Person("周老二",2));
map1.put("1", new Person("周老三",1));//key值重复,替换原value
//遍历打印map1,使用keySet方法
Set<String> set1 = map1.keySet();
for(String key:set1) {
Person value = map1.get(key);
System.out.println(key+"--->"+value);
/* 1--->Person [name=周老三, age=1]
* 2--->Person [name=周老二, age=2]
*/
}
/*创建HashMap集合
* key:Person,不能重复,需要重写hashCode和equals方法
* value:String,可以重复
*/
HashMap<Person,String> map2 = new HashMap<>();
map2.put(new Person("周老大",3), "1");
map2.put(new Person("周老二",2), "2");
map2.put(new Person("周老大",3), "3");//key值重复,替换原来的value
//遍历打印map2,使用entrySet方法
Set<Map.Entry<Person,String>> set2 = map2.entrySet();
for(Map.Entry<Person, String> entry:set2) {
Person key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"--->"+value);
/* Person [name=周老大, age=3]--->3
* Person [name=周老二, age=2]--->2
*/
}
}
}
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
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;
Person other = (Person) 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;
}
@Override
public String toString() {
return "Person [name=" + name + ", 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;
}
}
LinkedHashMap集合
java.util.LinkedHashMap<K,V> extends HashMap<K,V>
Map接口的哈希表和链接列表实现,具有可预知的迭代顺序
底层原理:哈希表+链表(记录元素的顺序)
import java.util.LinkedHashMap;
public class Demo13LinkedHashMap {
public static void main(String[] args) {
//创建一个LinkedHashMap集合
LinkedHashMap<Integer, String> linked = new LinkedHashMap<>();
linked.put(3, "三");
linked.put(1, "一");
linked.put(1, "二");
System.out.println(linked);//{3=三, 1=二} 有序,key值不允许重复
}
}
Hashtable集合
java.util.Hashtable<K,V>集合 implements Map<K,V>接口
Hashtable集合底层是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢。
HashMap集合底层是一个哈希表,是一个线程不安全的集合,是多线程集合,速度快。
Hashtable集合不能存储null键null值。
HashMap集合(之前学的所有集合)可以存储null键null值。
Hashtable和Vector集合一样,在jdk1.2之后被更先进的集合(HashMap、ArrayList)取代了。
Hashtable的子类Properties依然被使用,因为Properties集合是唯一一个与IO流相结合的集合。
JDK对集合添加的优化
List接口、Set接口、Map接口:里面添加了一个静态方法of,可以给集合一次性添加多个元素。
static<E> List<E> of(E...element)
【当集合中存储的元素个数已经确定了,不再改变时使用】
注意:
1.of方法只适用于List接口、Set接口、Map接口,不适用于接口的实现类。
2.of方法的返回值是一个不能改变的集合,集合不能再使用add和put方法添加元素,会出现异常(UnsupportedOperationException:不支持操作异常)
3.Set接口和Map接口在调用of方法的时候,不能有重复元素,否则会抛出异常(IllegalArgumentException:非法参数异常)