一、Collection集合
集合 : 集合是java中提供的一种容器,可以用来存储多个数据。
数组和集合都是容器,它们的区别
(1)数组长度是固定的,集合长度是可变的
(2)数组中存储的都是同一类型元素,可以存储基本数据类型值。集合存储的都是对象,而且对象的类型可以不一致,在开发中一般当对象多的时候,使用集合进行存储
集合框架
集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map
Collection:单列集合的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.list和java.util.set,其中list的特点是有序、元素可以重复,set的特点是元素无序、而且不可重复,List接口的主要实现类有java.util.ArrayList和java.util.LinkedList,Set接口的主要实现类有java.util.HashSet和java.util.TreeSet.
结构图
Collection
@Test
public void test1() {
//创建集合对象 可使用多态
Collection<String> coll = new ArrayList<String>();
System.out.println(coll); //重写了toString()方法
//添加
boolean b1 = coll.add("张三");
coll.add("李四");
coll.add("");
coll.add("王宇");
coll.add("天气");
//判断集合中是否包含指定对象
boolean b2 = coll.contains("李四");
//是否为空
boolean b3 = coll.isEmpty();
//大小
int size = coll.size();
//把集合中的元素存储到数组中
Object[] arr = coll.toArray();
for (Object object : arr) {
System.out.println(object);
}
coll.clear(); //清空集合元素不删除集合
}
Iterator迭代器
Collection接口和Map接口主要是存储元素,而Iterator主要用于迭代访问(遍历)Collection中的元素,因此Iterator对象也称为迭代器
public Interator iterator();获取集合对应的迭代器,用来遍历集合中的元素
/**
* 迭代器的使用步骤:
* 1、使用集合中的方法iterator()获取迭代器实现类对象,使用Iterator接口接收(多态)
* 2、使用iterator接口中的方法hashNext判断还有没有下一个元素
* 3、使用iterator接口中的方法next取出集合中的下一个元素
*/
@Test
public void iterator() {
Collection<String> coll = new ArrayList<>();
coll.add("姚明");
coll.add("杨幂");
coll.add("要从明");
Iterator<String> it = coll.iterator();
boolean b = it.hasNext();//判断集合中还有没有下一个元素
String s = it.next(); //取出集合中的元素
while(it.hasNext()) {
String str = it.next();
System.out.println(str);
}
System.out.println("------------------");
for(Iterator<String> it2=coll.iterator();it2.hasNext();) {
String str = it2.next();
System.out.println(str);
}
}
迭代器实现原理
增强for循环(只能进行遍历不能进行增删操作底层使用的就是迭代器)
@Test
public void foreach() {
int[] arr = {1,2,3,4,5};
for(int i : arr) {
System.out.println(i);
}
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
for(Integer i : list) {
System.out.println(i);
}
}
二、泛型
1、泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候可以使用泛型
2、泛型可以看成是一个变量来接收数据类型
E e :Element元素
T t :Type类型
3、使用泛型的好处
/**
* 不使用泛型:弊端不安全、不方便
*/
@Test
public void show() {
//创建集合对象 不使用泛型 默认就是Object类型
ArrayList list = new ArrayList();
list.add("111");
list.add(1);
Iterator it = list.iterator();
while(it.hasNext()) {
Object object = it.next();
System.out.println(object);
//想使用String类的特有方法length获取字符串长度
String s = (String)object; //会报错
}
}
/**
* 使用泛型好处
* 1、避免类型转换异常,存储的是什么类型,取出的就是什么类型
* 2、把运行期异常(代码运行之后抛出的异常)提升到了编译器(写代码的时候会报错)
*/
@Test
public void show2() {
ArrayList<String> list = new ArrayList<>();
list.add("1");
Iterator<String> it = list.iterator();
while(it.hasNext()) {
String s = it.next();
System.out.println(s.length());
}
}
4、自定义泛型类模拟ArrayList集合
public class CollectionTest<E> {
private E name;
public E getName() {
return name;
}
public void setName(E string) {
this.name = string;
}
}
@Test
public void GenericClass() {
CollectionTest<Integer> gc = new CollectionTest<>();
gc.setName(21);
Integer name = gc.getName();
CollectionTest<String> gc2 = new CollectionTest<>();
gc2.setName("234");
String strName = gc2.getName();
}
5、含有泛型的方法和接口
@Test
public <E> void methodGenericClass() {
System.out.println("含有泛型的方法");
}
/**
* 含有泛型的静态方法
*/
@Test
public static <E> void methodStaticGenericClass() {
System.out.println("含有泛型的静态方法");
}
/**
* 指定接口泛型
*
* @param <I>
*/
public interface GenericInterface<I> {
}
6、泛型通配符(注意泛型没有继承概念)
@Test
public static void test(ArrayList<?> list) {
Iterator<?> it = list.iterator();
while(it.hasNext()) {
Object obj = it.next();
System.out.println(obj);
}
}
7、受限泛型(泛型上限与泛型下限)
/**
* 泛型上限 : ? extends E 代表使用的泛型只能是E的子类或本身
* 泛型下限 : ? super E 代表使用的泛型只能是E的父类或本身
*/
Collection<Number> coll = null;
public static void getextends(Collection<? extends Number> coll);
public static void getextends(Collection<? super Number> coll);
三、List集合
1、List接口特点
java.util.list接口extends Collection接口
有序集合,存储元素和取出元素的顺序是一致的(存储123取出123)
有索引,包含了一些带索引的方法
允许存储重复元素
2、List集合常用方法
防止:集合索引越界(数组索引越界,字符串索引越界)
package com.huke.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("a");
System.out.println(list); //【a,b,c,a】 不是地址重写了toString()方法
list.add(3,"hu");
System.out.println(list); //【a,b,c,hu,a】
String remove = list.remove(2); //移除c 返回被移除的元素
//用指定元素替换集合中指定位置元素的位置
String setE = list.set(3, "A");
for(int i = 0;i < list.size();i++) {
System.out.println(list.get(i));
}
Iterator<String> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
for (String string : list) {
System.out.println(string);
}
}
}
3、ArrayList集合特点
(1)数组长度不可以改变,ArrayList集合长度可以改变
(2)对于ArrayList集合来说,直接打印得到的不是地址,而是内容,如果内容为空,得到的是空的中括号【】
(3)ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,
(4) ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。
(5)ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问,实现了Cloneable接口,能被克隆。
4、ArrayList集合常用方法
package com.huke.test;
import java.util.ArrayList;
public class ArrayListTest {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
System.out.println(list); //[]
//添加方法返回boolean类型
boolean succese = list.add("张三");
//返回指定索引数据
String name = list.get(0);
//返回被删除元素
String whoRemove = list.remove(0);
//集合长度
int size = list.size();
}
}
5、ArrayList集合存储的基本数据
如果希望向集合ArrayList当中存储基本数据类型,必须使用基本类型的包装类
基本类型 ------------------------------- 包装类(引用类型,包装类位于java.lang包下)
byte------------------------Byte
short-------------------------Short
int-------------------------------Integer
long---------------------------Long
float----------------------------Float
double----------------------Double
char---------------------------Character
boolean-----------------------------Boolean
6、ArrayList底层实现
(1)首先有三种方式来初始化:
public ArrayList();
默认的构造器,将会以默认的大小来初始化内部的数组
public ArrayList(Collection<? extends E> c)
用一个ICollection对象来构造,并将该集合的元素添加到ArrayList
public ArrayList(int initialCapacity)
(2)ArrayList底层是数组,复制一个数组来扩容
(3)扩容的方法就是 add(E e)
(4) int newCapacity = oldCapacity + (oldCapacity >> 1);
oldCapacity >> 1 右移运算符 原来长度的一半 再加上原长度也就是每次扩容是原来的1.5倍
之前的所有都是确定新数组的长度,确定之后就是把老数组copy到新数组中,这样数组的扩容就结束了
(5)无参数构造器代码是初始长度为10
7、LinkedList集合特点
(1)底层是一个链表结构。查询慢增删快
(2)里边儿包含了大量操作首元素的方法
(3)LinkedList是一个双向链表,如图
8、LinkedList常用方法
package com.huke.test;
import java.util.LinkedList;
public class LinkedListTest {
public static void main(String[] args) {
show01();
show02();
show03();
}
private static void show03() {
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("a");
linkedList.add("b");
linkedList.add("c");
System.out.println(linkedList); //[a,b,c]
if(!linkedList.isEmpty()) {
//移除第一个元素
linkedList.removeFirst();
linkedList.poll();
//移除最后一个元素
linkedList.removeLast();
}
}
private static void show02() {
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("a");
linkedList.add("b");
linkedList.add("c");
System.out.println(linkedList); //[a,b,c]
linkedList.clear(); //清空集合中的元素
if(!linkedList.isEmpty()) {
linkedList.getFirst();
linkedList.getLast();
}
}
private static void show01() {
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("a");
linkedList.add("b");
linkedList.add("c");
System.out.println(linkedList); //[a,b,c]
//将指定元素添加到头
linkedList.addFirst("www");
linkedList.push("www"); //和addFirst()等价
//将指定方法添加到末尾
linkedList.addLast("com");
}
}
9、Vector集合
Vector集合底层也是数组和ArrayList一样、单线程且同步。
四、Set集合
1、Set接口特点(java.util.Set接口 extends Collection接口)
(1)不允许存储重复元素
(2)没有索引,没有带索引的方法也不能使用普通for循环遍历
2、HashSet集合特点(java.util.HashMap集合 imlements Set接口)
(1)不允许重复元素
(2)没有索引,没有带索引的方法,也不能使用普通的for循环遍历
(3)是一个无序的集合,存储元素和取出元素的顺序有可能不一致
(4)底层是一个hash表(HashMap实例 查询的速度非常快)
3、Set集合遍历(迭代器 增强for)
package com.huke.test;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(1);
set.add(2);
set.add(3);
Iterator<Integer> it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
for (Integer integer : set) {
System.out.println(integer);
}
}
}
4、Set集合不允许存储重复元素原理
set集合存储不重复元素的的前提:必须重写hashCode和equlas放法
5、HashSet集合存储自定义类型元素
重写HashCode()和Equals()方法
package com.huke.test;
import java.util.HashSet;
/**
* Set集合不允许存储重复元素
*
* @author 32456
*
*/
public class SetSaveStringTest {
public static void main(String[] args) {
HashSet<Person> set = new HashSet<>();
Person p1 = new Person("小美女", 18);
Person p2 = new Person("小美女", 18);
Person p3 = new Person("小美女", 19);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
}
}
class Person {
private String name;
private int 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;
}
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 + "]";
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
6、LinkedHashSet集合特点(LinkedHashSet extends HashSet)
(1)底层是一个哈希表(数组+链表/红黑树)+链表;多了一条链表(记录元素的顺序),保证元素有序
package com.huke.test;
import java.util.HashSet;
import java.util.LinkedHashSet;
public class LinkedHashSetTest {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("www");
set.add("www");
set.add("abc");
set.add("huke");
System.out.println(set);
LinkedHashSet<String> linkedHashSetTest = new LinkedHashSet<>();
linkedHashSetTest.add("www");
linkedHashSetTest.add("www");
linkedHashSetTest.add("abc");
linkedHashSetTest.add("huke");
System.out.println(linkedHashSetTest);
}
}
7、可变参数(JDK1.5)
使用前提:当方法的参数列表数据类型已经确定,但是参数个数不确定,就可以使用可变参数
使用格式: 定义方法时使用
修饰符 -------返回值类型--------方法名(数据类型…变量名字){}
可变参数的原理:
可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数,传递的参数个数,可以是0个(不传递),1,2…多个
可变参数有多个必须写在末尾
package com.huke.test;
public class VarArgsTest {
public static void main(String[] args) {
int i = add(10, 20);
System.out.println(i);// 打印一个数组
}
// 定义计算(0-n)整数的方法 数据类型已经确定 参数个数不确定
public static int add(int... arr) {
System.out.println(arr);
System.out.println(arr.length);
int sum = 0;
for (int i : arr) {
sum += i;
}
return sum;
}
public static Object method(Object... objects) {
for (Object object : objects) {
System.out.println(object);
}
return objects;
}
}
五、Collections
1、comparable接口实现compareTo()方法
package com.huke.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
//往集合中添加多个元素
Collections.addAll(list, "q","2","2","4");
//打乱集合元素顺序
Collections.shuffle(list);
//默认升序排序
Collections.sort(list);
List<Person2> personList = new ArrayList<>();
personList.add(new Person2("张三",18));
personList.add(new Person2("王五",17));
personList.add(new Person2("人人",15));
Collections.sort(personList);
}
}
class Person2 implements Comparable<Person2>{
private String name;
private int age;
//Collections方法使用的前提被排序的集合里边儿存储的元素,必须实现Comparable接口
//重写接口中的方法compareTo()定义排序规则
/**
* 重写排序规则
* @param o
* @return
*/
@Override
public int compareTo(Person2 o) {
//return 0;//认为元素都是相同的
//自定义比较的规则,比较两个人的年龄(this,参数Person2)
return this.getAge() - o.getAge(); //年龄升序排序
}
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 "Person2 [name=" + name + ", age=" + age + "]";
}
public Person2() {
super();
// TODO Auto-generated constructor stub
}
public Person2(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
2、Comparator和Comparable的区别
Comparable : 自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较规则
Compartor :相当于找一个第三方裁判 比较两个
package com.huke.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CollectionsTestSort {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(3);
list.add(2);
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2; //前边儿减去后边默认升序
}
});
List<Person3> person3List = new ArrayList<>();
Collections.sort(person3List,new Comparator<Person3>() {
@Override
public int compare(Person3 o1, Person3 o2) {
//按照年龄升序排序
int result =o1.getAge() - o2.getAge();
//如果年龄一样 用姓名比较
if(result == 0) {
result = o1.getName().charAt(0) - o2.getName().charAt(0);
}
return result;
}
});
}
}
class Person3 {
private String name;
private int 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 "Person3 [name=" + name + ", age=" + age + "]";
}
public Person3() {
super();
// TODO Auto-generated constructor stub
}
public Person3(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
六、Map集合
1、Map<K,V>集合特点
(1)Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
(2)Map集合中的元素,key和value的数据额类型可以相同也可以不相同
(4)Map集合中的元素,key是不允许重复的,value是可以重复的
(5)Map集合中的元素,key和value是一一对应的
2、HashMap、LinkedHashMap集合特点
java.util.HashMap<K,V> 集合 implements Map<K,V>接口
(1)HashMap集合底层是哈希表:查询的速度特别快
JDK1.8之前 :数组 + 单项链表
JDK1.8之后 : 数组 + 单项链表/红黑树(链表长度超过8):提高查询的速度
(2)HashMap集合是一个无序集合,存储元素和取出元素的顺序有可能不一致
LinkedHashMap<K,V> 集合继承 HashMap<K,V>集合
(1)LinkedHashMap集合底层是哈希表+链表(保证迭代顺序)
(2)LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的
3、Map接口中的常用方法
package com.huke.collection;
import java.util.HashMap;
import java.util.Map;
public class MapTest {
public static void main(String[] args) {
show01();
show02();
show03();
show04();
}
private static void show04() {
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖", 168);
map.put("是多少" , 165);
map.put("令制冷", 178);
boolean b1 = map.containsKey("赵丽颖");
}
private static void show03() {
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖", 168);
map.put("是多少" , 165);
map.put("令制冷", 178);
Integer v1 = map.get("赵丽颖"); //返回对应值
Integer v2 = map.get("赵丽颖2"); //返回null
}
/**
* key存在 返回被删除的值
* key不存在 v返回null
*/
private static void show02() {
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖", 168);
map.put("是多少" , 165);
map.put("令制冷", 178);
int v2 = map.remove("赵丽颖"); //制动拆箱 会报错 null不能赋值给int却可以赋值给Integer
Integer v3 = map.remove("赵丽颖");
}
/**
* 存储键值对 key重复时 :会使用新的的value值替换重复的value
* 存储键值对 key不重复时,返回value
*/
private static void show01() {
//创建Map集合 多态
Map<String,String> map = new HashMap<>();
String v1 = map.put("李晨", "范冰冰1");
System.out.println(v1);
String v2 = map.put("李晨", "范冰冰2");
System.out.println(v2);
map.put("冷风","龙小云");
map.put("liukaiwei","养猫");
map.put("杨幂","刘恺威");
}
}
4、Map集合遍历键找值方式(keySet())
(1)使用Map集合中的方法keySet(),把集合中所有的key取出来,存储到一个set集合中
(2)遍历set集合,获取Map集合中的每一个key
(3)通过Map集合中的方法get(key)通过key找到value
package com.huke.collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class KeySetTst {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖", 168);
map.put("是多少" , 165);
map.put("令制冷", 178);
Set<String> set = map.keySet();
Iterator<String> it = set.iterator();
while(it.hasNext()) {
String key = it.next();
Integer value = map.get(key);
System.out.println(value);
}
for (String key : map.keySet()) {
Integer value = map.get(key);
System.out.println(value);
}
}
}
5、Entry键值对对象遍历(entrySet())
(1)使用Map集合中的方法entrySet(),把Map集合中的多个Entry对象取出来,存储到一个Set集合中
(2)遍历Set集合,获取到每一个Entry对象
(3)使用Entry对象中的方法getKey()和getValue()获取键与值
package com.huke.collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class EntrySetTest {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("赵丽颖", 168);
map.put("是多少", 165);
map.put("令制冷", 178);
Set<Map.Entry<String, Integer>> set = map.entrySet();
Iterator<Map.Entry<String, Integer>> it = set.iterator();
while(it.hasNext()) {
Map.Entry<String, Integer> entry = it.next();
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key);
System.out.println(value);
}
for (Map.Entry<String, Integer> entry : set) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key);
System.out.println(value);
}
}
}
6、使用HashMap存储自定义类型键值
Map集合保证key唯一 :
作为key元素,必须重写hashCode方法和equals方法,以保证key唯一
package com.huke.collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* @author 32456
*
*/
public class HashMapPersonSavePersonTest {
public static void main(String[] args) {
show01();
show02();
}
/**
* 存储自定义类型键值
* key :Person类
* value : String
*/
private static void show02() {
Map<Person,String> map = new HashMap<>();
map.put(new Person("女王",18),"英国");
map.put(new Person("秦始皇",18),"中国");
map.put(new Person("女王",18),"毛里裘是");
Set<Map.Entry<Person, String>> set = map.entrySet();
for (Entry<Person, String> entry : set) {
Person key = entry.getKey(); //必须重写HashCode和equals方法
String value = entry.getValue();
System.out.println(key+value);
}
}
private static void show01() {
Map<String, Person> map = new HashMap<String, Person>();
map.put("北京", new Person("张三",18));
map.put("北京", new Person("李四",18));
map.put("北京", new Person("王五",18));
map.put("北京", new Person("张三",18));
Set<String> set = map.keySet();
for (String key : set) {
Person value = map.get(key);
System.out.println(value);
}
}
}
class Person {
private String name;
private Integer age;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
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 == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
}
}
7、LinkedHashMap集合
LinkedHashMap extends HashMap<K,V>
底层原理 :
哈希表 + 链表(记录元素的顺序)
package com.huke.collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class LinkedHashMapTest {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("a", "a");
map.put("b", "b");
map.put("c", "c");
map.put("d", "d");
System.out.println(map); //key不允许重复无序
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("a", "a");
linkedHashMap.put("b", "b");
linkedHashMap.put("c", "c");
linkedHashMap.put("d", "d");
System.out.println(linkedHashMap);
}
}
8、Hashtable集合
Hashtable集合 implements Map<K,V>接口
Hashtable :底层是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
Hashtable集合不能存储null值,null键
Hashtable和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了
Hashtable的子类集合Properties依然活跃在历史舞台
Properties集合是唯一一个和IO流相结合的集合
HashMap集合(除了Hashtable的所有集合):可以存储null值,null键
package com.huke.collection;
import java.util.HashMap;
import java.util.Hashtable;
public class HashtableTest {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put(null, "1");
map.put("1", null);
map.put(null, null);
Hashtable<String, String> hashtable = new Hashtable<>();
hashtable.put(null, null); //报错 空指针异常
}
}
9、练习计算一个字符串每个字符出现的个数
package com.huke.collection;
import java.util.HashMap;
import java.util.Scanner;
public class MapTestChongfu {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
char[] arr = str.toCharArray();
HashMap<Character, Integer> map = new HashMap<>();
for (char key : arr) {
if(map.containsKey(key)) {
Integer value = map.get(key);
value ++;
map.put(key, value);
}else {
map.put(key, 1);
}
}
for (Character key : map.keySet()) {
Integer value = map.get(key);
System.out.println(value);
}
}
}
10、JDK9集合中的add()方法都添加了静态方法的优化of()方法
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
public class MapTestChongfu {
public static void main(String[] args) {
List<Integer> list = List.of(1,2,3,4,5);
Set<Integer> set = Set.of(1,2,3,4);
HashMap<String,Integer> map = HashMap.of("张三","张三","李四",18);
}
}