Java中的集合(Collection,Map)
集合类体系结构
Collection集合
Collection集合概述
- 是单例集合的顶层接口,它表示一组对象,这些对象也被成为Collection元素
- JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现
创建Collection集合的对象
- 多态的方式
- 具体的实现类ArrayList
List集合中存储的元素是可以重复的,即如果两个相同值得元素 ,地址会不相同。而Set中不可重复元素,如果两个元素得值相同,则会共用一个地址。
Collection集合的常用方法
- boolean add( E e ):添加元素
- boolean remove( Object o ):从集合中移除指定元素
- void clear():清空集合中的元素
- boolean contains( Object o ):判断集合中是否存在指定元素
- boolean isEmpty():判断集合是否为空
- int size():返回集合的长度
Collection集合的遍历
Iterator :迭代器,集合的专用遍历方式
- Iterator< E > iterator():返回集合中元素的迭代器,通过集合的iterator()方法得到
- 迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的
Iterator 中的常用方法
- E next():返回迭代中的下一个元素
- boolean hasNext():如果迭代具有更多元素,则返回true
public static void main(String[] args) {
Collection<String> c = new ArrayList<>(); // 创建集合对象
strings.add("I");
strings.add("Love");
strings.add("Java");
strings.add("And");
strings.add("JavaScript");
Iterator<String> it = c.iterator(); // 返回集合中元素的迭代器
while(it.hasNext()){
System.out.println(it.next());
}
}
例题:Collection集合存储学生对象并且遍历
public static void main(String[] args) {
Collection<Student> students = new ArrayList<>();
students.add(new Student(1,"蜡笔小新",5));
students.add(new Student(2,"风间彻",5));
students.add(new Student(3,"樱田妮妮",5));
Iterator<Student> it = students.iterator();
while(it.hasNext()){
Student next = it.next();
System.out.println("学号为:" + next.getNumber() + "\t\t姓名为:" + next.getName() + "\t\t年龄为:" + next.getAge());
}
}
// 学号为:1 姓名为:蜡笔小新 年龄为:5
// 学号为:2 姓名为:风间彻 年龄为:5
// 学号为:3 姓名为:樱田妮妮 年龄为:5
List集合
List集合概述和特点
集合概述
- 有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素兵搜索列表中的元素
- 与Set集合不同,列表通常允许重复的元素
特点
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可以重复
创建集合对象的方法
List< E > list = new ArrayList< E >();
List集合常用方法
- void add( int index, E element):在此集合指定位置插入元素
- E remove( int index ):删除指定索引出处的元素,返回被修改的元素
- E set( int index, E element):修改指定索引处的元素,返回被修改的元素
- E get( int index):返回指定索引处的元素
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("I");
list.add("Love");
list.add("Java");
list.add("And");
list.add("JavaScript");
System.out.println(list); // [I, Love, Java, And, JavaScript]
list.add(1,"JavaWeb");
System.out.println(list); // [I, JavaWeb, Love, Java, And, JavaScript]
System.out.println(list.remove(1)); // JavaWeb
System.out.println(list.remove("And")); // true
System.out.println(list.set(1,"OvO")); // Love
System.out.println(list); // [I, OvO, Java, JavaScript]
System.out.println(list.get(2)); // Java
}
List存储学生数组并遍历的方式与Collection集合的方式一样,只不过List集合可以使用for循环进行遍历
使用迭代器遍历集合时,不允许在集合中添加/删除元素,但是可以修改元素,因为增加/删除元素会触发并发修改异常,这个异常可以通过分析源码理解,如果想要在遍历中根据条件增加/删除元素操作,可以使用for循环遍历
ListIterator 迭代器
ListIterator中的常用方法
- E next():返回迭代中的下一个元素
- boolean hasNext():判断迭代是否还有元素
- E previous():返回迭代中的上一个元素
- boolean hasPrevious():判断迭代的反方向是否还有更多元素
- void add( E e ):增加元素
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
ListIterator<String> it = list.listIterator();
while(it.hasNext()){
System.out.print(it.next() + " "); // a b c d
}
System.out.println();
while(it.hasPrevious()){
System.out.print(it.previous() + " "); // d c b a
}
System.out.println();
while(it.hasNext()){
String next = it.next();
if(next.equals("a")){
it.add("java");
}
}
System.out.println(list); // [a, java, b, c, d]
}
listIterator 与 Iterator的区别
ListIterator是List集合特有的迭代器,通过List集合的 listIterator() 方法得到,它允许我们沿任一方向遍历列表,并且可以在迭代期间修改列表
前者在调用add()方法时,会将实际的修改值赋值给预期的修改值,而后者的add()方法中则不会进行此赋值,所以前者可以在迭代的时候进行增加或者删除元素( add() remove() ),而后者是不行的,否则会出现并发修改异常
List集合子类特点
List集合常用子类:ArrayList , LinkedList
- ArrayList:底层数据结构是数组,查询快,增删慢
- LinkedList:底层数据结构是链表,增删快,查询慢
ArrayList<String> array = new ArrayList<String>();
LinkedList<String> linked = new LinkedList<String>();
LinkedList集合常用功能
- public void addFirst( E e ):在该列表开头插入指定元素
- public void addLast( E e ):在该列表末尾追加指定元素
- public E getFirst():返回此列表中的第一个元素
- public E getLast():返回此列表中的最后一个元素
- public E removeFirst():从列表中删除并返回第一个元素
- public E removeLast():从列表中删除并返回最后一个元素
public static void main(String[] args) {
LinkedList<String> strings = new LinkedList<>();
strings.add("I");
strings.addFirst("Love");
strings.addLast("Java");
System.out.println(strings); // [Love, I, Java]
System.out.println(strings.getFirst()); // Love
System.out.println(strings.getLast()); // Java
System.out.println(strings.removeFirst()); // Love
System.out.println(strings.removeLast()); // Java
System.out.println(strings); // [I]
}
ArrayList
Set集合
Set集合的特点
- 不包含重复元素的集合
- 没有带索引的方法,所以不能使用普通for循环遍历
public static void main(String[] args) {
Set<String> strings = new HashSet<String>(); // HashSet对迭代顺序不做任何保证(不保证存储和取出的数据顺序一致)
strings.add("a");
strings.add("b");
strings.add("c");
strings.add("d");
strings.add("a");
Iterator<String> it = strings.iterator();
for (String s:strings) {
System.out.print(s + "\t"); // a b c d 重复元素自动合并
}
}
哈希值
哈希值是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
- public int hashCode():返回对象的哈希码值
public static void main(String[] args) {
Student s1 = new Student(1, "蜡笔小新", 5);
Student s2 = new Student(2, "风间彻", 5);
System.out.println(s1.hashCode()); // 1160460865
System.out.println(s2.hashCode()); // 1247233941
System.out.println("hello".hashCode()); // 99162322
System.out.println("java".hashCode()); // 3254818
System.out.println("hello".hashCode()); // 99162322
System.out.println("重地".hashCode()); // 1179395
System.out.println("通话".hashCode()); // 1179395
}
- 同一个对象的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的,不过我们可以通过重写hashCode()方法来让不同对象的哈希值相同
HashSet
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以是部包含重复元素的集合
public static void main(String[] args) {
HashSet<String> strings = new HashSet<>();
strings.add("1"); // 注意此处开始的存储顺序是无序的
strings.add("2");
strings.add("6");
strings.add("7");
strings.add("3");
strings.add("5");
strings.add("4");
strings.add("9");
strings.add("10");
for (String s:strings) {
System.out.print(s + "\t"); // 1 2 3 4 5 6 7 9 10 取出的顺序与存储的顺序不一致
}
}
HashSet保证元素唯一性的过程
在存入数据时,HashSet会做以下操作
- 判断哈希表是否初始化,如果未初始化,则进行初始化
- 根据对象的哈希值计算对象的存储位置,如果该位置没有元素,则存储元素
- 存入的元素与以前的元素比较哈希值
- 如果哈希值不同,则存入元素
- 如果哈希值相同,则调用对象的equals()方法进行比较
- 如果不相同,则存入元素,如果相同,则说明重复,不存入元素
如果使用HashSet来存储并且遍历学生数组的话
HashSet<Student> hashSet = new HashSet<Student>();
Student s1 = new Student(1,"A",1);
Student s2 = new Student(1,"A",1);
hashSet.add(s1);
hashSet.add(s2);
// 两个对象都会存入
为了避免存储重复值的对象,我们需要在学生类中重写hashCode() 以及equals() 方法,使用快速重写自动生成方法即可
哈希表
哈希表底层采用数组 + 链表实现,可以说是一个元素为链表的数组
哈希表的默认长度为16
LinkedHashSet集合
LinkedHashSet集合的特点
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复的元素
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();
TreeSet
TreeSet集合特点
- 元素会按照一定的规则排序,具体排序方式取决于构造方法
- TreeSet():根据元素的自然排序进行排序
- TreeSet( Comparator comparator ):根据指定的比较器进行排序
- 没有带索引的方法,所以不能用普通for循环遍历
- 由于是Set集合,所以不包含重复元素的集合
TreeSet<Integer> treeSet = new TreeSet<Integer>();
自然排序Comparable的使用
例题:使用TreeSet存储学生信息,并且按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
// Student.java
public class Student implements Comparable<Student>{
private int number;
private String name;
private int age;
public Student(int number,String name,int age){
this.number = number;
this.name = name;
this.age = age;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
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(Student s) { // 重写compareTo方法
// return 0; // 返回0则认为该元素重复,不添加数据
// return 1; // 升序输出,如果没指定元素,只有return,则按照输入顺序升序输出
// return -1; // 降序输出
int i = this.age - s.age; // this相当于s2 , o相当于s1
int i2 = i==0?this.name.compareTo(s.name):i;
return i2; // 如果为0则不添加,如果大于0则升序排序,如果小于0则降序排序
}
}
// main.java
public static void main(String[] args) {
TreeSet<Student> students = new TreeSet<Student>();
students.add(new Student(1,"lbxx",4));
students.add(new Student(2,"fjc",8));
students.add(new Student(3,"ytnn",2));
students.add(new Student(4,"ad",7));
students.add(new Student(5,"zn",1));
students.add(new Student(6,"cm",3)); // 年龄相同,则对姓名按照字母进行排序
students.add(new Student(6,"bm",3));
students.add(new Student(6,"am",3));
for (Student s:students) {
System.out.println(s.getNumber() + "\t\t" + s.getName() + "\t\t" + s.getAge());
}
}
/*
5 zn 1
3 ytnn 2
6 am 3
6 bm 3
6 cm 3
1 lbxx 4
4 ad 7
2 fjc 8
*/
比较器排序Comparator的使用
TreeSet<Student> students = new TreeSet<Student>(new Comparator<Student>() { // 匿名内部类重写方法
@Override
public int compare(Student s1, Student s2) { // s1 则相当于 this
int num1 = s1.getAge() - s2.getAge(); // 不能访问属性,使用方法获取属性
int num2 = num1 == 0 ? s1.getName().compareTo(s2.getName()) : num1;
return num2;
}
});
- 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
- 比较器排序,就是**让集合构造方法接收Comparator的实现类对象,**重写compare( T o1 , T o2)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
例题:用自然排序或比较器排序对学生进行总分排序,如果总分一样则按照姓名排序
// Students.java
public class Students implements Comparable<Students>{ // 自然排序比较法
private int id;
private String name;
private double chinese;
private double math;
private double english;
private double sum;
public Students(){
}
public Students( int id, String name, double chinese, double math, double english){
this.id = id;
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
this.sum = this.chinese + this.math + this.english;
}
public double getSum() {
return sum;
}
public void setSum(float sum) {
this.sum = sum;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getChinese() {
return chinese;
}
public void setChinese(float chinese) {
this.chinese = chinese;
}
public double getMath() {
return math;
}
public void setMath(float math) {
this.math = math;
}
public double getEnglish() {
return english;
}
public void setEnglish(float english) {
this.english = english;
}
@Override
public int compareTo(Students s) {
int num = (int) (this.sum - s.sum);
int num2 = num == 0 ? this.getName().compareTo(s.getName()) : num;
return num2;
}
}
// main.java
import java.util.*;
public class main {
public static void main(String[] args) {
TreeSet<Students> students = new TreeSet<Students>(); // 自然排序法的TreeSet定义
/*TreeSet<Students> students = new TreeSet<Students>(new Comparator<Students>() {
@Override
public int compare(Students s1, Students s2) { // 比较器排序方法
int num = (int) (s1.getSum() - s2.getSum());
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
return num2;
}
});*/ // 比较器排序法的TreeSet定义
students.add(new Students(1,"d",65,78,45));
students.add(new Students(2,"h",34,56,77));
students.add(new Students(3,"r",23,46,89));
students.add(new Students(4,"j",45,79,47));
students.add(new Students(5,"q",54,68,98));
students.add(new Students(6,"k",87,58,87));
students.add(new Students(7,"m",27.5,64,79.5));
Iterator<Students> it = students.iterator();
while(it.hasNext()){
Students s1 = new Students();
s1 = it.next();
System.out.println(s1.getId() + "\t\t" + s1.getName() + "\t\t" + s1.getChinese() + "\t\t" + s1.getMath() + "\t\t" + s1.getEnglish() + "\t\t" + s1.getSum());
}
}
}
如果使用比较器排序法,那么Students类就不用继承Comparable接口
Map集合
Map集合概述
- interface Map < K , V >:键值对
- 将键映射到值的对象,不能包含重复的键,每个键可以映射到最多一个值
创建Map集合
- 多态的方式
- 具体的实现类:HashMap
public static void main(String[] args) {
Map<String, String> map = new HashMap<String , String>();
map.put("翻斗花园","胡图图");
map.put("春日部","蜡笔小新");
map.put("清水市","樱桃小丸子");
// map.put("清水市","野比大雄"); 如果新添加的数据和以前的数据键相同,但是值不相同,那么新的值就会把以前的值覆盖
System.out.println(map); // {翻斗花园=胡图图, 春日部=蜡笔小新, 清水市=樱桃小丸子}
// System.out.println(map); // {翻斗花园=胡图图, 春日部=蜡笔小新, 清水市=野比大雄}
}
Map集合常用方法
- V put( K key , V value):添加元素,返回该键对应的值
- V remove( Object key):根据键值对删除元素,返回该键对应的值,如果没有则返回null
- void clear():移除所有键值对元素
- boolean containsKey( Object key ):判断集合是否包含指定的键
- boolean containsValue( Object value):判断集合是否包含指定的值
- boolean isEmpty():判断集合是否为空
- int size():集合的长度
public static void main(String[] args) {
Map<String, String> map = new HashMap<String , String>();
map.put("翻斗花园","胡图图");
map.put("春日部","蜡笔小新");
map.put("清水市","樱桃小丸子");
System.out.println(map); // {翻斗花园=胡图图, 春日部=蜡笔小新, 清水市=樱桃小丸子}
System.out.println(map.remove("翻斗花园")); // 胡图图
System.out.println(map); // {春日部=蜡笔小新, 清水市=樱桃小丸子}
System.out.println(map.containsKey("春日部")); // true
System.out.println(map.containsValue("樱桃小丸子")); // true
System.out.println(map.isEmpty()); // false
System.out.println(map.size()); // 2
map.clear();
System.out.println(map); // {}
}
Map集合的获取功能
- V get( Object key ):根据键获取值,返回获取的值,没有则返回null
- Set < K > KeySet():获取所有键的集合,键是唯一的,所以使用Set集合
- Collection < V > values():获取所有值的集合
- Set < Map.Entry < K , V > > entrySet():获取所有键值对对象的集合
public static void main(String[] args) {
Map<String, String> map = new HashMap<String , String>();
map.put("翻斗花园","胡图图");
map.put("春日部","蜡笔小新");
map.put("清水市","樱桃小丸子");
System.out.println(map.get("春日部")); // 蜡笔小新
Set<String> strings = map.keySet();
for (String s:strings) {
System.out.print(s + "\t"); // 翻斗花园 春日部 清水市
}
System.out.println();
Collection<String> values = map.values();
for (String s:values) {
System.out.print(s + "\t"); // 胡图图 蜡笔小新 樱桃小丸子
}
}
Map集合的遍历
方法1:先获取键所组成的集合,使用Map的 get() 方法来根据键寻找对应的值,然后进行输出
public static void main(String[] args) {
Map<String, String> map = new HashMap<String , String>();
map.put("翻斗花园","胡图图");
map.put("春日部","蜡笔小新");
map.put("清水市","樱桃小丸子");
Set<String> strings = map.keySet();
for (String s:strings) {
System.out.println("key = " + s + "\tvalue = " + map.get(s));
// key = 翻斗花园 value = 胡图图
// key = 春日部 value = 蜡笔小新
// key = 清水市 value = 樱桃小丸子
}
}
方法2:先获取所有键值对对象的集合,遍历集合,得到每一个键值对对象( Set < Map.Entry < K , V > > entrySet() )
public static void main(String[] args) {
Map<String, String> map = new HashMap<String , String>();
map.put("翻斗花园","胡图图");
map.put("春日部","蜡笔小新");
map.put("清水市","樱桃小丸子");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> s : entries){ // 注意此处接收对象的类型
System.out.println("key = " + s.getKey() + "\tvalue = " + s.getValue());
// key = 翻斗花园 value = 胡图图
// key = 春日部 value = 蜡笔小新
// key = 清水市 value = 樱桃小丸子
}
}
例题:HashMap存储学生数据并且遍历输出
// Student.java
public class Student {
private int number;
private String name;
private int age;
public Student(int number,String name,int age){
this.number = number;
this.name = name;
this.age = age;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
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;
}
}
// main.java
public static void main(String[] args) {
Map<String, Student> map = new HashMap<>();
map.put("A",new Student(1,"蜡笔小新",5));
map.put("B",new Student(2,"风间彻",5));
map.put("C",new Student(3,"樱田妮妮",5));
Set<Map.Entry<String, Student>> entries = map.entrySet();
for ( Map.Entry<String, Student> s: entries) {
System.out.println("key = " + s.getKey() + "\t学号为:" + s.getValue().getNumber() + "\t姓名为:" + s.getValue().getName() + "\t年龄为:" + s.getValue().getAge());
// key = A 学号为:1 姓名为:蜡笔小新 年龄为:5
// key = B 学号为:2 姓名为:风间彻 年龄为:5
// key = C 学号为:3 姓名为:樱田妮妮 年龄为:5
}
}
例题:HashMap存储学生数据,以学生为键,地址为值进行存储并遍历,如果学生对象的成员变量值相同,我们就认为是同一个对象
// Student.java
import java.util.Comparator;
import java.util.Objects;
public class Student{
private int number;
private String name;
private int age;
public Student(int number,String name,int age){
this.number = number;
this.name = name;
this.age = age;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
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) { // equals()方法
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return number == student.number &&
age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() { // hashCode()方法
return Objects.hash(number, name, age);
}
}
// main.java
import java.util.*;
public class Demo{
public static void main(String[] args) {
Map<Student, String> map = new HashMap<>();
map.put(new Student(1,"蜡笔小新",5),"春日部");
map.put(new Student(2,"风间彻",5),"向日葵班");
map.put(new Student(3,"樱田妮妮",5),"双叶幼稚园");
map.put(new Student(1,"蜡笔小新",5),"日本"); // 用来测试重复学生数据的覆盖
Set<Map.Entry<Student, String>> entries = map.entrySet();
for ( Map.Entry<Student, String> s: entries) {
System.out.println("居住地为:" + s.getValue() + "\t学号为:" + s.getKey().getNumber() + "\t姓名为:" + s.getKey().getName() + "\t年龄为:" + s.getKey().getAge());
// 居住地为:向日葵班 学号为:2 姓名为:风间彻 年龄为:5
// 居住地为:双叶幼稚园 学号为:3 姓名为:樱田妮妮 年龄为:5
// 居住地为:日本 学号为:1 姓名为:蜡笔小新 年龄为:5
}
}
}
关于生成hashCode() 和 equals() 方法,IDEA中在Student类中使用 alt + insert 快捷键,选中equals() 和 hashCode() 方法进行生成
一路默认下一步即可。
ArrayList嵌套HashMap
public static void main(String[] args) {
ArrayList<Map<String, String>> array = new ArrayList<>();
Map<String, String> map1 = new HashMap<String,String>();
map1.put("春日部","蜡笔小新");
map1.put("唐","杜甫");
Map<String, String> map2 = new HashMap<String,String>();
map2.put("清水","樱桃小丸子");
map2.put("唐","李白");
Map<String, String> map3 = new HashMap<String,String>();
map3.put("翻斗花园","胡图图");
map3.put("明","朱熹");
array.add(map1);
array.add(map2);
array.add(map3);
int count = 1;
for (Map<String, String> s:array) {
System.out.println("这是ArrayList中的第" + count + "组数据");
for (Map.Entry<String, String> a:s.entrySet()) {
System.out.println("键为:" + a.getKey() + "\t值为:" + a.getValue());
}
count++;
}
/*
for (Map<String, String> s:array) { // 第二种遍历方法
Set<String> strings = s.keySet();
System.out.println("这是ArrayList中的第" + count + "组数据");
for (String key:strings) { // key为键
String value = s.get(key);
System.out.println("键为:" + key + "\t值为:" + value);
}
count++;
}
*/
}
/* 这是ArrayList中的第1组数据
键为:唐 值为:杜甫
键为:春日部 值为:蜡笔小新
这是ArrayList中的第2组数据
键为:唐 值为:李白
键为:清水 值为:樱桃小丸子
这是ArrayList中的第3组数据
键为:翻斗花园 值为:胡图图
键为:明 值为:朱熹 */
HashMap嵌套ArrayList
public static void main(String[] args) {
Map<String, ArrayList<String>> map = new HashMap<>();
ArrayList<String> array1 = new ArrayList<String>();
array1.add("Java");
array1.add("JavaScript");
ArrayList<String> array2 = new ArrayList<String>();
array2.add("Sql");
array2.add("MySql");
ArrayList<String> array3 = new ArrayList<String>();
array3.add("MyBaits");
array3.add("Spring");
map.put("A",array1);
map.put("B",array2);
map.put("C",array3);
Set<Map.Entry<String, ArrayList<String>>> entries = map.entrySet();
int count = 1;
for (Map.Entry<String, ArrayList<String>> s:entries) {
System.out.println("这是HashMap中的第" + count + "组数据");
ArrayList<String> value = s.getValue();
System.out.print("键为:" + s.getKey() + "\t值数组为:");
for (String val:value) { // val为ArrayList数组
System.out.print(val + "\t");
}
System.out.println();
count++;
}
}
/* 这是HashMap中的第1组数据
键为:A 值数组为:Java JavaScript
这是HashMap中的第2组数据
键为:B 值数组为:Sql MySql
这是HashMap中的第3组数据
键为:C 值数组为:MyBaits Spring */
统计字符串中每个字符出现次数
要求从键盘输入字符串,输出格式如下a(1)b(2)c(3)…
分析:因为要统计次数,所以我们设置 HashMap 中键为字符,值为次数, HashMap< Character , Integer >。将字符作为键,保证键唯一,才能进行次数统计。在录入集合的过程中,如果这个键值在集合中不存在,则存入键,设置值为1;如果这个键已经存在了,那就让值加一之后,重新将键和值存入集合,键因为存在,所以新值会覆盖旧值。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串:");
String line = sc.nextLine(); // 获取输入的字符串 acddbegladgingm
HashMap<Character, Integer> hashMap = new HashMap<Character, Integer>(); // 设置 HashMap
// 如果使用HashMap,有的时候输出并不会按照字符进行排序,这时我们可以改用 TreeMap
// TreeMap<Character, Integer> hashMap = new TreeMap<Character, Integer>();
// TreeMap会对键进行排序
for (int i = 0; i < line.length(); i++) {
char key = line.charAt(i); // 循环设置key
Integer value = hashMap.get(key); // 获取该键对应的值
if(value == null){ // 值为null表示该键不存在
hashMap.put(key,1); // 存入键,设置值为1
}else{ // 该键已经存在了
value++; // 让值加一
hashMap.put(key,value); // 重新存入集合
}
}
StringBuilder str = new StringBuilder(); // 用StringBuilder来设置输出格式
Set<Map.Entry<Character, Integer>> entries = hashMap.entrySet();
for (Map.Entry<Character, Integer> s:entries) {
str.append(s.getKey()).append("(").append(s.getValue()).append(")");
}
System.out.println(str.toString()); // a(2)b(1)c(1)d(3)e(1)g(3)i(1)l(1)m(1)n(1)
}
如果要对键进行排序,那么就使用TreeMap
Collections
Collections类的概述
是针对集合操作的工具类
Collections类的常用方法
- public static < T extends Comparable< ? super T > > void sort( List < T > list )::将指定的列表按升序排序
- public static void reverse( List < ? > list ):反转指定列表中元素的顺序
- public static shufflereverse( List < ? > list ):使用默认的随机源随机排列指定的列表。也就是每次调用随机排列元素
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for(int i = 0 ; i < 10 ; i++)
{
Random num = new Random();
list.add(num.nextInt(20) + 1);
}
System.out.println(list); // [2, 4, 9, 5, 2, 20, 8, 6, 19, 10]
Collections.sort(list);
System.out.println(list); // [2, 2, 4, 5, 6, 8, 9, 10, 19, 20]
Collections.reverse(list);
System.out.println(list); // [20, 19, 10, 9, 8, 6, 5, 4, 2, 2]
Collections.shuffle(list); // 每一次调用都会重新随机排列
System.out.println(list); // [8, 19, 4, 20, 5, 2, 9, 2, 10, 6]
Collections.shuffle(list);
System.out.println(list); // [10, 20, 9, 4, 2, 2, 19, 6, 5, 8]
}
上一篇: 两种子查询的区别