1 区别
1.1 数组
长度固定
可以存储基本类型和引用类型
1.2 集合
长度不固定
只能存储引用类型,存储基本类型则通过装箱操作,把基本类型装箱到引用类型保存到集合当中。
集合在java.util.*包下
2 Collection接口
2.1 介绍

ArrayList【重点】【常用】: 数组结构实现,查询快、增删慢; JDK1.2版本,运行效率快、线程不安全。
Vector: 数组结构实现,查询快、增删慢; JDK1.0版本,运行效率慢、线程安全。
LinkedList: 链表结构实现,增删快,查询慢。
增删快:前一个元素的头指向后一个元素的尾,在元素1和元素2中间增加一个元素3时,只是把元素1的尾由本来指向元素2的头改成指向元素3的头,元素3的尾指向元素2的头。删除也同理,把元素1和元素2中间的元素3删去,只需要把元素1的尾指向元素2的头,元素3回收。
查询慢:通过指针从头到尾的索引逐个找到下一个元素所在地址
Collection接口提供的方法:
boolean add (0bject obj) //添加一一个对象。
boolean addAll (Collection c) //将一个集合中的所有对象添加到此集合中。
void clear() //清空此集合中的所有对象。
boolean contains (Object o) //检查此集合中是否包含o对象(调用indexOf方法——先把传过来的o与实例化的那个类进行equals比较,两者在内存中地址相同才为true,如果传过来的o是一个new 类(xxx),则返回false,因为地址不同)
boolean equals (Object o) //比较此集合是否 与指定对象相等。
boolean isEmpty() //判断此集合是否为空
boolean remove (0bject o) //在此集 合中移除o对象(也会先调用equals方法判断传过来的对象和集合中存在的对象是否是同一地址,是返回true并执行删除,否则返回false)
int size() //返回此集合中的元素个数。
0bject[] toArray() // 将此集合转换成数组。
等等
2.2 存储基本类型
CollectionTest.java
import java.util.*;
public class CollectionTest {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("张三"); //添加元素
c.add("李四");
c.add("王五");
System.out.println("元素个数:"+c.size());
System.out.println(c); //重写了toString方法 自动调用toString
c.remove("张三"); //删除元素
System.out.println(c);
Collection co = new LinkedList();
co.add("ZS");
co.add("LS");
co.add("WW");
System.out.println(co);
for (Object o : co) {
System.out.println(o);
}
for (Object o : c) { //集合的遍历只能增强型for循环
System.out.println(o);
}
Iterator iterator = co.iterator(); //迭代器iterator
while (iterator.hasNext()){
String next = (String)iterator.next();
System.out.println(next);
iterator.remove(); //用迭代器的remove才能删除,如果用collection.remove会报错并发修改异常
}
System.out.println(co);
}
}
结果

迭代器iterator遍历集合时不能使用Collection原有的方法。
2.3 存储引用类型
Student.java 实体类
package jiheTest.collection;
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;
}
}
CollectionTest2.java
import java.util.*;
public class CollectionTest2 {
public static void main(String[] args) {
Collection collection = new ArrayList();
Student s1 = new Student("张三",16);
Student s2 = new Student("李四",12);
Student s3 = new Student("王五",26);
collection.add(s1);
collection.add(s2);
collection.add(s3);
System.out.println(collection.toString());
System.out.println(collection);
System.out.println("-------增强for---------");
for (Object o : collection) {
Student s = (Student)o ;
System.out.println(s);
}
System.out.println("-------迭代器iterator---------");
Iterator iterator = collection.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
结果

3 List接口
3.1 特点
有序,有下标,元素可重复
3.2 方法
void add(int index,Object o) //在index位置插入对象o。 boolean addAll(int index,Collection c) //将一个集合中的元素添加到此集合中的 index位置。 Object get(int index) //返回集合中指定位置的元素。 List subList(int fromIndex,int toIndex) //返回fromIndex和toIndex之间的集合元素。左闭右开区间。
等等
3.3 遍历
import java.util.*;
public class ListTest {
public static void main(String[] args) {
List l = new ArrayList();
l.add("A");
l.add("B");
l.add(0,"C");//下标0处插入一个元素,其他往后推一位
System.out.println(l);
System.out.println(l.get(1));//A
System.out.println(l.subList(0,2));//C,A 不包括下标2即B,左闭右开。
System.out.println("--------可以用普通for遍历List-------");
for (int i = 0; i < l.size(); i++) { //l的长度用size方法获取
System.out.println(l.get(i)); //用get方法传参i获取对应下标的元素
}
System.out.println("---------也可以用增强for-----------");
for (Object o : l) {
System.out.println(o);
}
System.out.println("----------还可以使用迭代器----------");
Iterator iterator = l.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("========使用List接口新增的方法Listiterator列表迭代器==============");
ListIterator listIterator = l.listIterator();
System.out.println("-----------hasNext-----------从前往后遍历,遍历完指针在列表最后一项");
while (listIterator.hasNext()){
System.out.println(listIterator.nextIndex()+":"+listIterator.next());
}
System.out.println("-----------hasPrevious-------从后往前,从指针开始位置向前移到第一项");
while (listIterator.hasPrevious()){
System.out.println(listIterator.previousIndex() + ":" + listIterator.previous());
}
System.out.println("indexOf方法获取某元素下标,元素B的下标"+l.indexOf("B"));
}
}
结果:

3.4 添加,删除基本类型
import java.util.*;
public class ListTest2 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(10); //此时进行装箱操作,把基本类型封装成一个引用类型存储进去
list.add(20);
list.add(30);
list.add(40);
list.add(50);
System.out.println(list);
// System.out.println("---------list.remove(10)不能直接删除元素‘10’,默认指定删除下标为10的元素,列表长度不够则报错下标越界-------");
// list.remove(10);
System.out.println("-------强转为Integer的对象来删除--------");
list.remove((Integer)10);
System.out.println(list);
System.out.println("-------强转为Object的对象来删除--------");
list.remove((Object)20);
System.out.println(list);
System.out.println("------new一个Integer对象来删除,相当于把它变成一个引用类型了-------");
list.remove(new Integer(30));
System.out.println(list);
System.out.println("---------用for倒叙遍历------------------");
for (int i = list.size()-1; i >=0 ; i--) {
System.out.println(list.get(i));
}
}
}
结果

4 ArrayList(实现List接口的类)
数组结构实现,查询快、增删慢; JDK1.2版本,运行效率快、线程不安全。
4.1 重写实体类中的equals方法
Student.java:
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;
}
//重写equals方法 ************************************
@Override
public boolean equals(Object obj) {
if(obj==this){
return true;
}
if(obj==null){
return false;
}
if(obj instanceof Student){
if(((Student) obj).getName().equals(this.name)&&((Student) obj).getAge()==this.age){
return true;
}
}
return false;
}
}
ArrayList.java:
import java.util.*;
public class ArrayListTest {
public static void main(String[] args) {
List list = new ArrayList();
Student student = new Student("某某",22);
list.add(student);
System.out.println(list);
System.out.println("包含contains "+list.contains(new Student("某某",22)));//没重写Student类中的equals前 false,重写后 true
System.out.println("查询下标indexOf"+list.indexOf(new Student("某某",22)));
System.out.println("删除remove"+list.remove(new Student("某某",22)));
System.out.println(list);
}
}
结果:

查看ArrayList的源码


indexOf方法,remove方法,lastIndexOf方法等都有用到equals,而contains方法中又调用到indexOf方法,所以重写equals方法会影响这些方法,本来删除方法remove中传一个new 类()返回结果是false,重写之后比较的不是判断equals传过来的对象是否和实体类在内存中地址相同,而是判断传过来对象的各字段内容是否与列表中某对象的各字段内容相同。
4.2 部分源码分析
ArrayList a = new ArrayList<> new一个集合对象时,size的大小为0,容量为0;
当调用add添加1个元素时,容量变为10(常量DEFAULT_CAPACITY),超过10之后每次都扩容到原来的1.5倍,即15,22,33,50,75......
源码中elementData是存放元素的数组。
5 Vector(实现List接口的类)
数组结构实现,查询快、增删慢; JDK1.0版本,运行效率慢、线程安全。
现在开发用的不多,了解即可。
使用
import java.util.*;
public class VectorTest {
public static void main(String[] args) {
Vector vector= new Vector<>();
// 增
vector.add("张三");
vector.add("李四");
vector.add("王五");
// 删
/* vector.remove(0);
vector.remove("王五");
System.out.println(vector);
vector.clear();
System.out.println(vector);
*/
// 改
vector.set(2, "某某");
// 查(遍历)
System.out.println("--------用elements方法遍历--------");
Enumeration elements = vector.elements();
while (elements.hasMoreElements()){
System.out.println(elements.nextElement());
}
System.out.println("--------用增强for循环-----------");
for (Object o : vector) {
System.out.println(o);
}
System.out.println("--------用普通for循环-----------");
for (int i = 0; i < vector.size(); i++) {
System.out.println(vector.get(i));
}
System.out.println("============================");
System.out.println("第一个元素:"+vector.firstElement());
System.out.println("最后一个元素:"+vector.lastElement());
}
}
结果:

6 LinkedList(实现List接口的类)
(双向)链表结构实现,增删快,查询慢。
方法和ArrayList基本一样
特有方法:

源码
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
与ArrayList区别

(图源自B站“千锋Java”)
7 Set接口和HashSet实现类
7.1 Set特点
元素不重复,遍历顺序:无序。
7.2 HashSet集合特点
底层数据结构是哈希表
对集合的迭代顺序不保证:不保证存储和取出的元素顺序一致
没有带索引的方法,所以不能使用普通for循环遍历
由于是Set集合,所以HashSet集合也不包含重复元素
7.3 保证元素不重复的源码流程

所以要保证元素唯一性,就要重写hashCode和equals方法
7.4 重写equals和hashCode方法
实体类中重写equals和hashCode方法:
实体类中alt+insert选择equals() and hashCode() 然后一路next,最后直接finish就可以

重写后的Student.java:
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;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
测试添加属性值相同的两个对象
HashSetTest.java:
import java.util.HashSet;
public class HashSetTest {
public static void main(String[] args) {
HashSet<Student> hs = new HashSet<Student>();
Student s1 = new Student("张三", 18);
Student s2 = new Student("李四", 19);
Student s3 = new Student("王五", 20);
Student s4 = new Student("王五", 20); //重写Student类中的hashCode和equals方法后,重复字段的对象就不能存入hashSet中。
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
System.out.println(hs);
}
}
结果:
[Student{name='王五', age=20}, Student{name='张三', age=18}, Student{name='李四', age=19}]
7.5 数据结构中的哈希表HashMap
jdk8之前,底层采用数组+链表实现,是一个元素为链表的数组
jdk8之后,在长度比较长的时候,底层实现了优化
默认初始长度为16
7.6 补充之LinkedHashSet集合
LinkedHashSet集合特点
哈希表和链表实现的Set接口,具有可预测的迭代次序
由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
由哈希表保证元素唯一,也就是说没有重复的元素

图自黑马程序员
8 TreeSet集合概述

图自黑马程序员
自然排序Comparable
是TreeSet集合的无参构造
TreeSet<Student> ts = new TreeSet<Student>();
Student.java
public class Student implements Comparable<Student>{
// 实现Comparable时重写的compareTo方法,通过比较存入的对象来排序
// 先存入1个,再存入第2个时,与第1个比较,返回0不存入集合中,返回大于0存入第1个的后面,小于0存入第1个前面。
// 存入第3个时,与上述最后比较的元素进行比较,原理相同。
@Override
public int compareTo(Student o) {
return this.age-o.age==0?this.name.compareTo(o.name):this.age-o.age; //同岁数(2对象年龄相差为0)则返回2对象名字字母比较的结果,否则按岁数相差来。String类重写了compareTo方法,按字母来排序
}
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;
}
}
TreeSetTest.java:
public class TreeSetTest {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>();
Student s1 = new Student("zhangsan", 18);
Student s2 = new Student("lisi", 22);
Student s3 = new Student("wangwu", 23);
Student s4 = new Student("moumou", 19);
Student s5 = new Student("abani", 18); //年龄相同时按字母排序
Student s6 = new Student("abani", 18); //不添加重复元素
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
for (Student t : ts) {
System.out.println(t.getName() + ":" + t.getAge());
}
}
}
结果:
abani:18
zhangsan:18
moumou:19
lisi:22
wangwu:23
比较器Comparator
TreeSet的有参构造方法
用匿名内部类的方式
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num = o1.getAge() - o2.getAge();
int num2 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;
return num2;
}
});
TreeSet.java:
package jiheTest.collection;
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num = o1.getAge() - o2.getAge();
int num2 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;
return num2;
}
});
Student s1 = new Student("zhangsan", 18);
Student s2 = new Student("lisi", 22);
Student s3 = new Student("wangwu", 23);
Student s4 = new Student("moumou", 19);
Student s5 = new Student("abani", 18); //年龄相同时按字母排序
Student s6 = new Student("abani", 18); //不添加重复元素
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
for (Student t : ts) {
System.out.println(t.getName() + ":" + t.getAge());
}
}
}
Student.java中则不用实现 Comparable
运行结果同上。
练习:存入1-20不重复随机数并遍历
代码
import java.util.*;
public class RandomTest {
public static void main(String[] args) {
Set<Integer> set = new HashSet<Integer>(); //生成的随机数是无序的
// TreeSet<Integer> set = new TreeSet<>(); //生成的随机数会经过自然排序
Random random = new Random();
while (set.size()<10){
int num = random.nextInt(20)+1;//随机数 0~19 +1
set.add(num);
}
// for (Integer integer : set) {
// System.out.println(integer);
// }
Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
结果是1到20混乱排序的10个数
但是有一个问题,如果随机数换成从1~10,存入HashSet,遍历出来结果反而是有序的,因为插入HashSet的是Integer,其hashCode()实现就返回int值本身。所以在对象hashCode这一步引入了巧合的“按大小排序”。
JDK8版java.util.HashMap内的hash算法比JDK7版的混淆程度低;在[0, 2^16-1]范围内经过HashMap.hash()之后还是得到自己。
例子正好落入这个范围内。外加此例中这个HashMap没有hash冲突,这就导致例中元素有序插入HashMap的开放式哈希表里。
所以存入之前加上2^16 遍历时再减去2^16 就可以在这个范围之外,就能实现无序。但是每次运行时都是这个顺序。

如果是列表ArrayList则可以用Collections提供的方法shuffle传入列表对象,直接就将此列表中的元素打乱排序。
9 泛型
黑马程序员笔记
泛型:
是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译检测到非法的类型它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数 一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型,这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口
泛型定义格式: <类型>:指定一种类型的格式。这里的类型可以看成是形参 <类型1类型2.>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参 将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型
泛型的好处: 把运行时期的问题提前到了编译期间 避免了强制类型转换
9.1 泛型类
泛型实体类
GenericTest.java:
public class GenericTest<T> { //泛型类
private T t ;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public T show(T t){
return t;
}
}
GenericTest2.java:
public class GenericTest2 {
public static void main(String[] args) {
GenericTest<String> s1 = new GenericTest<String>();
s1.setT("lqx");
System.out.println(s1.getT());
GenericTest<Integer> s2 = new GenericTest<Integer>();
s2.setT(123);
System.out.println(s2.getT());
GenericTest<Boolean> s3 = new GenericTest<Boolean>();
s3.setT(true);
System.out.println(s3.getT());
System.out.println("--------------------------");
GenericTest<Boolean> s4 = new GenericTest<Boolean>();
System.out.println(s4.show(false));
GenericTest<Integer> s5 = new GenericTest<Integer>();
System.out.println(s5.show(321));
GenericTest<String> s6 = new GenericTest<String>();
System.out.println(s6.show("lisi"));
GenericTest<Double> s7 = new GenericTest<Double>();
System.out.println(s7.show(0.0));
}
}
结果:
lqx
123
true
--------------------------
false
321
lisi
0.0
9.2 泛型方法
GenericMethodTest.java:
public class GenericMethodTest {//普通类
public <T> void show(T t ){ //泛型方法
System.out.println(t);
}
}
GenericTest2.java:
public class GenericTest2 {
public static void main(String[] args) {
GenericMethodTest g1 = new GenericMethodTest();
g1.show(true);
g1.show(111);
g1.show("wangwu");
g1.show(1.2);
}
}
结果:
true
111
wangwu
1.2
9.3 类型通配符

9.4 可变长参数的使用
Arrays工具类中有一个静态方法: public static List asList(T... a): 返回由指定数组支持的固定大小的列表
返回的集合不能做增删操作,可以做修改操作
List接口中有一个静态方法: public static List of(E... elements): 返回包含任意数量元素的不可变列表
返回的集合不能做增删改操作
Set接口中有一个静态方法: public static Set of(E...elements): 返回一个包含任意数量元素的不可变集合
在给元素的时候,不能给重复的元素
返回的集合不能做增删操作,没有修改的方法
10 Map
10.1 使用
MapTest.java:
import java.util.*;
public class MapTest {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1,"zs");
map.put(2,"ls");
map.put(3,"ww");
map.put(3,"zl"); //当K相同时,把最新的值加进去,相当于update修改操作。HsahMap能保证键K的唯一性,值V是可以重复的。
System.out.println(map);
}
}
结果
{1=zs, 2=ls, 3=zs}
10.2 常用方法
| 方法名 | 说明 |
|---|---|
| V put(K key,V value) | 添加元素 |
| V remove(Object key) | 根据键删除键值对元素 |
| void clear() | 移除所有的键值对元素 |
| boolean containsKey(Object key) | 判断集合是否包含指定的键 |
| boolean containsValue(Object value) | 判断集合是否包含指定的值 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 集合的长度,也就是集合中键值对的个数 |
| V get(Object key) | 根据键获取值 |
| Set keySet() | 获取所有键的集合 |
| Collection values() | 获取所有值的集合 |
| Set<Map.Entry<K,V>> entrySet() | 获取所有键值对对象的集合 |
示例代码 MapTest.java:
package jiheTest.collection;
import java.util.*;
public class MapTest {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1,"zs");
map.put(2,"ls");
map.put(3,"ww");
Set<Integer> keySet = map.keySet();
for (Integer key : keySet) {
System.out.println(key);
System.out.println(map.get(key));
}
Set<Map.Entry<Integer, String>> entries = map.entrySet();
System.out.println(entries);
for (Map.Entry<Integer, String> entry : entries) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
结果:
1
zs
2
ls
3
ww
[1=zs, 2=ls, 3=ww]
1:zs
2:ls
3:ww
10.3 ArrayList内嵌HashMap
也可以说是ArrayList内嵌HashMap,这种数据类型有点类似于JavaScript中的列表[{对象},{对象}...]数据,前端的JSON数据。
ArrayListAndHashMap.java:
import java.util.*;
public class ArrayListAndHashMap {
public static void main(String[] args) {
ArrayList<HashMap<String, String>> arrayList = new ArrayList<>();
HashMap<String, String> hm1 = new HashMap<>();
hm1.put("神枪手","枪炮师");
hm1.put("鬼剑士","阿修罗");
arrayList.add(hm1);
HashMap<String, String> hm2 = new HashMap<>();
hm2.put("格斗家","气功师");
hm2.put("魔法师","元素师");
arrayList.add(hm2);
HashMap<String, String> hm3 = new HashMap<>();
hm3.put("圣职者","驱魔师");
hm3.put("暗夜使者","刺客");
arrayList.add(hm3);
System.out.println(arrayList);
for (HashMap<String, String> hashMaps : arrayList) {
Set<Map.Entry<String, String>> hashMap = hashMaps.entrySet();
for (Map.Entry<String, String> hm : hashMap) {
System.out.println(hm.getKey()+"--转职-->"+hm.getValue());
}
}
}
}
结果:
[{鬼剑士=阿修罗, 神枪手=枪炮师}, {魔法师=元素师, 格斗家=气功师}, {暗夜使者=刺客, 圣职者=驱魔师}]
鬼剑士--转职-->阿修罗
神枪手--转职-->枪炮师
魔法师--转职-->元素师
格斗家--转职-->气功师
暗夜使者--转职-->刺客
圣职者--转职-->驱魔师
10.4 HashMap内嵌ArrayList
HashMapAndArrayList.java:
import java.util.*;
public class HashMapAndArrayList {
public static void main(String[] args) {
HashMap<String, ArrayList<String>> hashMap = new HashMap<>();
ArrayList<String> gjs = new ArrayList<>();
gjs.add("剑魂");
gjs.add("鬼泣");
hashMap.put("鬼剑士",gjs);
ArrayList<String> gdj = new ArrayList<>();
gdj.add("气功师");
gdj.add("柔道家");
hashMap.put("格斗家",gdj);
ArrayList<String> sqs = new ArrayList<>();
sqs.add("弹药专家");
sqs.add("漫游枪手");
hashMap.put("神枪手",sqs);
Set<Map.Entry<String, ArrayList<String>>> entries = hashMap.entrySet();
for (Map.Entry<String, ArrayList<String>> entry : entries) {
System.out.print(entry.getKey()+"包含职业:");
for (String s : entry.getValue()) {
System.out.print(" "+s);
}
System.out.println();
}
}
}
结果:
鬼剑士包含职业: 剑魂 鬼泣
格斗家包含职业: 气功师 柔道家
神枪手包含职业: 弹药专家 漫游枪手
另外,TreeMap是一种能排序的Map,类似于TreeSet