二万长文,概括Java中集合的大致用法, 做个字典就行!

本篇文章是一个学习java的笔记,概括集合中的 list ,Arraylist, HashMap, EnumMap, TreeMap, Properties, Set, Queue , PriorityQueue, Deque, Collections 的基本用法, 以及集合的各种重写方法手段,当个字典吧!

文章目录集合集合list:关于list的Tip:list集合与Array数组的相互转换list中比较需重写equals方法:映射表Map:关于map的tip枚举 EnumMap排序 TreeMap配置文件Properties:集合Set:队列Queue:优先队列PriorityQueue:双向队列 Deque:Collections类:

集合

声明:下面是整理的笔记, 想看原文点击链接

在Java中,如果一个Java对象可以在内部持有若干其他Java对象,并对外提供访问接口,我们把这种Java对象称为集合, 我们最开始了解的数组,其实也可以看作是一种集合。

java集合设计中存在二个特点,一是实现了接口和实现类相分离,例如,有序表的接口是List,具体的实现类有ArrayListLinkedList等,二是支持泛型,我们可以限制在一个集合中只能放入同一种数据类型的元素,例如:

public ArrayList<String> myList = new ArrayList<String>();  // 这个list只能存放string类型

因为数组存在一定的缺陷,并不能满足我们的编程要求。

数组初始化后大小不可变;
数组只能按索引顺序存取。

Java的java.util包主要提供了以下三种类型的集合:

List:一种有序列表的集合,例如,按索引排列的StudentList
Set:一种保证没有重复元素的集合,例如,所有无重复名称的StudentSet
Map:一种通过键值(key-value)查找的映射表集合,例如,根据Studentname查找对应StudentMap

集合list:

在集合类中, list作为最基础的一种集合, 他是有序列表,但不同于数组, 它可以进行内存的自动扩张和收缩, 并且list将添加和删除的操作封装起来了,使我们操作集合更简单,而不用去关心集合中的元素是如何移动的。

关于list的接口, 常见的接口方法如下:

在末尾添加一个元素:boolean add(E e)
在指定索引添加一个元素:boolean add(int index, E e)
删除指定索引的元素:int remove(int index)
删除某个元素:int remove(Object e)
获取指定索引的元素:E get(int index)
获取链表大小(包含元素的个数):int size()

常见的list子类, 有 ArrayList 和 LinkedList , 但是我们常用的还是ArrayList

比较如下:

描述 ArrayList LinkedList

获取指定元素
速度很快
需要从头开始查找元素

添加元素到末尾
速度很快
速度很快

在指定位置添加/删除
需要移动元素
不需要移动元素

内存占用

较大

关于list的Tip:

list可以允许我们加入相同的值

list可以允许们加入null值

创建list可以使用list的接口of()方法, 根据指定元素快速生成, 但是不允许加入null值

遍历list常用 for each 方法

public static void main(String[] args){
// 常规方法创建list
ArrayList<Integer> list = new ArrayList<Integer>();
// 可以允许我们加入相同的值
list.add('1');
list.add('1');
// 可以允许我们加入null值
list.add(null);

// 使用of() 方式快捷生成集合 但是这种方式不能加入null值
ArrayList<String> mylist = mylist.of("hello", "world");

// 遍历list
for(Integer integer:list){
System.out.println(integer);
}
// 或者像数组一样遍历
for(int i=0;i<list.size(); i++){
System.out.println(list.get(i));
}
}

list集合与Array数组的相互转换

list转换array

调用 toArray() 方式

public class Main {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
// 转换如下
String[] array = list.toArray(new String[list.size()]);
for (String s : array) {
System.out.println(s);
}
// 或者更简洁方式
String[] array = list.toArray(String[]::new);
}
}

array转换为list

​ 调用 List.of() 方式

Integer[] array = {2, 2, 2};
ArrarList<Integer> list = ArrayList.of(arrar);
// 如果是用List 作为接口, 那么返回的list只是一个只读list, 操作它就会出错。

list中比较需重写equals方法:

list作为一个有序列表, 按照先后顺序将数值存放, 所以我们可以根据索引值去获取特定值。

List还提供了boolean contains(Object o)方法来判断List是否包含某个指定元素。此外,int indexOf(Object o)方法可以返回某个元素的索引,如果元素不存在,就返回-1

先看一个例子:

public class Main {
public static void main(String[] args) {
List<String> list = List.of("A", "B", "C");
// 简单测试
System.out.prinln(list.contains("A")); // True
// 如果传入一个新的实例
System.out.prinln(list.contains(new String("A"))); //True
// 结果还是 True
}
}

根据上面代码, 在不同实例中,却得到了相同的结果, 原因是list内部使用了equals() 去判断元素是否相同,因此,要正确使用Listcontains()indexOf()这些方法,放入的实例必须正确覆写equals()方法,否则,放进去的实例,查找不到。我们之所以能正常放入StringInteger这些对象,是因为Java标准库定义的这些类已经正确实现了equals()方法, 所以如果自己创建了一个对象,那么就需要重写equals() 方法。

比如:

public class Main {
public static void main(String[] args) {
List<Person> list = List.of(
new Person("Xiao Ming", 90),
new Person("Xiao Hong", 98),
new Person("Bob", 50)
);
System.out.println(list.contains("Bob"));
}
}

class Person {
String name;
Integer score;
public Person(String name, Integer score) {
this.name = name;
this.score = score;
}
}

// 结果输出是false

如何正确的重写equals() 方法:

我们要注意这个方法要达到什么要求返回True, 比如上面代码, 当名字和分数相同,就返回True

所以我们这样编写:

public boolean equals(Object o) {
if (o instanceof Person) {
Person p = (Person) o;
return Objects.equals(this.name, p.name) && this.score == p.score;
}
return false;
}

把这个代码加到上面,就是这样的效果:

public class Main {
public static void main(String[] args) {
List<Person> list = List.of(
new Person("Xiao Ming", 90),
new Person("Xiao Hong", 98),
new Person("Bob", 50)
);
System.out.println(list.contains(new Person("Bob", 50)); // 比较的时候,传入一个泛型对象
}
}

class Person {
String name;
Integer score;
public Person(String name, Integer score) {
this.name = name;
this.score = score;
}
@Override
public boolean equals(Object o) {
if (o instanceof Person) { // 首先判断类型 确保不是null类型
Person p = (Person) o;
return Objects.equals(this.name, p.name) && this.score == p.score;
}
return false;
}
}

List中查找元素时,List的实现类通过元素的equals()方法比较两个元素是否相等,因此,放入的元素必须正确覆写equals()方法,Java标准库提供的StringInteger等已经覆写了equals()方法

编写equals()方法可借助Objects.equals()判断。

如果不在List中查找元素,就不必覆写equals()方法。

映射表Map:

在python中,我们知道有字典这样的键值对来达到映射的效果, 可以更快的查找特定的值, 但是在java中,也有Map,Map这种键值(key-value)映射表的数据结构,作用就是能高效通过key快速查找value(元素)。

比如在如下情况,我们查找指定的信息

package listTest;

import java.util.HashMap;

public class mapiter {
public HashMap<String, Student> map = new HashMap<>();

public mapiter() {
// 将"Xiao Ming"和Student实例映射并关联
map.put("Xiao Ming", new Student("Xiao Ming", 99));
}

public static void main(String[] args) {
mapiter m = new mapiter();
// 通过key查找并返回映射的Student实例
Student target = m.map.get("Xiao Ming");
// true,同一个实例
System.out.println(target.score);
// 99
Student another = m.map.get("Bob");
// 通过另一个key查找
System.out.println(another);
// 未找到返回null
}
}

class Student {
public String name;
public int score;

public Student(String name, int score) {
this.name = name;
this.score = score;
}
}

关于map的tip

如果要判断某个 key 是否存在, 我们可以使用 boolean containsKey(K key) 方法

对map中put相同的key, 不会报错,但是后者会覆盖前者信息, 最好还是单个存在

map中不存在顺序之说, 没有顺序,只有映射关系

对于map来说, 遍历存在二种方式。

package listTest;

import java.util.HashMap;
import java.util.Map;

public class mapiter {
public HashMap<String, Student> map = new HashMap<>();

public mapiter() {
// 将"Xiao Ming"和Student实例映射并关联
map.put("Xiao Ming", new Student("Xiao Ming", 99));
map.put("Xiao Gang", new Student("Xiao Gang", 87));
map.put("Xiao Hong", new Student("Xiao Hone", 99));
}
public void fun(){
// 正常遍历方法
System.out.println("for each 遍历");
for(String s: map.keySet()){
String name = map.get(s).name;
int score = map.get(s).score;
System.out.println(name + " = " + score);
}
}

public void fun2(){
// 其他方式遍历

System.out.println("其他方式遍历");
for(Map.Entry<String, Student> entry:map.entrySet()){
String name = entry.getValue().name;
Integer score = entry.getValue().score;
System.out.println(name + " = " + score);
}
}
public static void main(String[] args) {
mapiter m = new mapiter();
m.fun();
m.fun2();

}
}

class Student {
public String name;
public int score;

public Student(String name, int score) {
this.name = name;
this.score = score;
}
}

Map的内部,对key做比较是通过equals()实现的,这一点和List查找元素需要正确覆写equals()是一样的,即正确使用Map必须保证:作为key的对象必须正确覆写equals()方法。

我们经常使用String作为key,因为String已经正确覆写了equals()方法。但如果我们放入的key是一个自己写的类,就必须保证正确覆写了equals()方法,并且我们还要正确的编写 hashCode() 方法,因为 key计算索引的方式就是调用key对象的hashCode()方法,它返回一个int整数。HashMap正是通过这个方法直接定位key对应的value的索引,继而直接返回value,所以如果是自己写的类, 就必须重写这二个方法。

值得一提的是, 实际上HashMap初始化时默认的数组大小只有16, 当数据达到了上限, HashMap就会自动扩容, 我们也可以指定map容量

HashMap<String, Integer> map = new HashMap<>(10000);

重写方法

class Student {
public String name;
public int score;

public Student(String name, int score) {
this.name = name;
this.score = score;
}
// 重写equals()
@Override
public boolean equals(Object obj) {
if (obj instanceof Student){
Student st = (Student) obj;
return Objects.equals(this.name, st.name) && this.score == st.score;

}
return false;
}
// 重写hashCode()
@Override
public int hashCode() {
return Objects.hash(name, score);
}

// 必要的时候,还可以重写tostring()
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
}

枚举 EnumMap

HashMap是一种通过对key计算hashCode(),通过空间换时间的方式,直接定位到value所在的内部数组的索引,因此,查找效率非常高, 但是如果我们的key他是 enum 类型, 其实在这里,我们就可以使用 Java函数库中中的 EnumMap , 它在内部以一个非常紧凑的数组存储value,并且根据enum类型的key直接定位到内部数组的索引,并不需要计算hashCode(),不但效率最高,而且没有额外的空间浪费。

代码如下:

public void fun3() {
// 枚举对象 泛型擦拭
Map<DayOfWeek, String> map = new EnumMap<>(DayOfWeek.class);

map.put(DayOfWeek.MONDAY, "星期一");
map.put(DayOfWeek.TUESDAY, "星期二");
map.put(DayOfWeek.WEDNESDAY, "星期三");
map.put(DayOfWeek.THURSDAY, "星期四");
map.put(DayOfWeek.FRIDAY, "星期五");
map.put(DayOfWeek.SATURDAY, "星期六");
map.put(DayOfWeek.SUNDAY, "星期日");

for (DayOfWeek dayOfWeek : map.keySet()) {
String day = map.get(dayOfWeek);
System.out.println(dayOfWeek + "是" + day);
}

System.out.println(DayOfWeek.WEDNESDAY + "是" + map.get(DayOfWeek.WEDNESDAY));
}

排序 TreeMap

我们知道对于map来说, 他是没有顺序而言的, 是一种空间换时间的映射表, 但实际上还有一个map它可以实现sort排序 功能的, 就是SorteMap , 但是实现类是TreeMap。

       ┌───┐
| Map |
└───┘

┌────┴─────┐
│ │
┌───────┐ ┌─────────┐
│HashMap | │ SortedMap │
└───────┘ └─────────┘


┌─────────┐
│ TreeMap │
└─────────┘

比如我们看一个例子:

当key是String 或者 Integer 类的时候, 这个时候默认是升序排列,因为StringInteger这些类已经实现了Comparable接口,因此可以直接作为Key使用

public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new TreeMap<>();
map.put("orange", 1);
map.put("apple", 2);
map.put("pear", 3);
for (String key : map.keySet()) {
System.out.println(key + map.get(key));
}

}
}
// 最后输出 apple 2, orange 1, pear 3

但是如果我们的类自己编写的, 或者我们想改变排序方式呢? 怎么重写?

要实现 Comparator<>() 接口 具体实现,如下:

// 关于 object.compareTo(object) 函数
// 如果前者大于后者 返回 大于0的数
// 如果前者等于后者 返回0
// 如果前者小于后者 返回小于0的数

public void fun4() {
Map<Student, Integer> map4 = new TreeMap<>(new Comparator<Student>() {
// @Override // 默认升序排列
// public int compare(Student o1, Student o2) {
// return o1.name.compareTo(o2.name);
// }

@Override // 重写 降序
public int compare(Student o1, Student o2) {
if (o1.name.equals(o2.name)) {
return 0;
} else if (o1.name.compareTo(o2.name) > 0) {
return -1;
} else {
return 1;
}

}
});
map4.put(new Student("Xiao Ming", 99), 1);
map4.put(new Student("Xiao Gang", 87), 2);
map4.put(new Student("Xiao Hone", 99), 3);

// 遍历
for (Student student : map4.keySet()) {
String name = student.name;
System.out.println(name + map4.get(student));
}

}

class Student {
public String name;
public int score;

public Student(String name, int score) {
this.name = name;
this.score = score;
}
}

配置文件Properties:

很多时候,我们需要去读写配置文件,这些配置文件的特点就是 key-value 一般来说都是string-string 的类型, 所以我们完全是可以用 HashMap<String, String> 去实现这样功能

我们使用 Properties 去读取配置文件, 关于配置文件,

Java默认配置文件以.properties为扩展名,所以我们要在当前目录下新建一个 setting.properties 的文件, 然后每行以key=value表示,以#课开头的是注释。如下是最简单的配置文件:

# setting.properties

last_open_file=hello.txt
auto_save_interval=60
username=me

然后怎么读取这个配置文件 方法如下:(这个是调用文件流)


String f = "D:\\java\\java代码\\package\\listTest\\setting.properties";
Properties props = new Properties();
props.load(new java.io.FileInputStream(f)); //导入一个文件流
String filepath = props.getProperty("last_open_file");
String interval = props.getProperty("auto_save_interval", "120");
System.out.println(filepath);

具体步骤分三步:

    创建Properties实例; as: Properties props = new Properties();
    调用load()读取文件; as: props.load(inputSteam) 可以文件流 字节流 也可以资源流
    调用getProperty()获取配置。

我们试试一个字节流的调用方法: (使用字节流,要注意每一个key-value 要有换行)

public void fun5() throws IOException {
/*读取字节流*/

String settings = "# test \n course=Java \n last_open_date=2019-08-07T12:35:01" +
"\n username=shalouzaixyua";
ByteArrayInputStream input = new ByteArrayInputStream(settings.getBytes("UTF-8"));
// 创建一个Properties实例
Properties props = new Properties();
// 调用load读取一个字节流
props.load(input);
// 调用getProperty获得配置文件
System.out.println("course: " + props.getProperty("course"));
System.out.println("last_open_date: " + props.getProperty("last_open_date"));
System.out.println("last_open_file: " + props.getProperty("last_open_file"));
System.out.println("auto_save: " + props.getProperty("auto_save", "60"));
System.out.println("The author:" + props.getProperty("username"));
// 写入一个新的配置文件
props.setProperty("id", "888888888");
// 重新读取这个配置文件
System.out.println("The id:" + props.getProperty("id"));

}

集合Set:

我们知道map是用来存储不重复的key-value 映射对, 那如果我们只是想保存不重复的key呢? 我们可以直接用Set,它可以用于存储不重复的元素集合,类似python中的set集合。

主要方法如下:

将元素添加进Set<E>boolean add(E e)
将元素从Set<E>删除:boolean remove(Object e)
判断是否包含元素:boolean contains(Object e)

简单例子:

Set<String> set = new HashSet<>();
set.add("abc");
set.remove("abc");
set.contains("abc"); // false

因为set只是存储key的一个集合,所以我们可以用这个达到去重的效果, 这里要注意一点,放入set的key类都必须正确实现equals() 方法 和 hashcode() 方法。

我们的set接口用一张图表示:

			Set
|
________________
| |
HashSet SorteSet
|
TreeSet

HashSet是无序的,因为它实现了Set接口,并没有实现SortedSet接口;
TreeSet是有序的,因为它实现了SortedSet接口。

如果我们随意的输出Hashset中的元素

public class Main {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("pear");
set.add("orange");
for (String s : set) {
System.out.println(s);
}
}
}
// 顺序是随意的 不确保
// banana pear apple orange

如果我们输出TreeSet中的元素

public class Main {
public static void main(String[] args) {
Set<String> set = new TreeSet<>();
set.add("apple");
set.add("banana");
set.add("pear");
set.add("orange");
for (String s : set) {
System.out.println(s);
}
}
}

// apple banana orange pear A-Z的升序
// 如果要更改排序 需要重写tree中的compare方法

练习二种去重方法:

package listTest;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;

public class Set {
public static void main(String[] args) throws IOException {
List<Message> received = List.of(
new Message(1, "Hello!"),
new Message(2, "你在干嘛?"),
new Message(2, "你在干嘛啊啊?"),
new Message(3, "去哪吃饭?"),
new Message(3, "去哪吃饭?"),
new Message(4, "滚")
);
List<Message> displayMessages = process(received); // 调用函数
for (Message message : displayMessages) {
System.out.println(message.text);
}
fun();
}

static List<Message> process(List<Message> received) {
// TODO: 第一种方式
// HashSet<Integer> set = new HashSet<>();
// ArrayList<Message> newList = new ArrayList<>();
// for(Message message:received){
// // 如果不存在 就放得进去
// if(set.add(message.sequence)){
// newList.add(message);
// }
// }
//
// return newList;
// }
// reveived 是一个包含重复sequence的集合list

TreeSet<Message> set = new TreeSet<>(new Comparator<Message>() {
@Override
//TODO: 按照sequence 达到去重效果 第二种方式
public int compare(Message o1, Message o2) {
return o1.sequence > o2.sequence ? 1 : (o1.sequence < o2.sequence ?
-1 : 0);
}
});
for(Message message:received){
set.add(message);
}
return new ArrayList<Message>(set);
}

}

class Message {
public final int sequence;
public final String text;

public Message(int sequence, String text) {
this.sequence = sequence;
this.text = text;
}

@Override
public String toString() {
return sequence + ":" + text;
}
}


队列Queue:

队列(Queue)是一种经常使用的集合。Queue实际上是实现了一个先进先出(FIFO:First In First Out)的有序表。它和List的区别在于,List可以在任意位置添加和删除元素,而Queue只有两个操作:

把元素添加到队列末尾;
从队列头部取出元素。

queue有如下方法:

int size():获取队列长度;
boolean add(E)/boolean offer(E):添加元素到队尾;
E remove()/E poll():获取队首元素并从队列中删除;
E element()/E peek():获取队首元素但并不从队列中删除。

除了size() 只有一种方式, 其他方法都有二种, 二种的操作都是一样的, 但是对异常的处理情况不一样。

方法 throw Exception 返回false或null

添加元素到队尾
add(E e)
boolean offer(E e)

取队首元素并删除
E remove()
E poll()

取队首元素但不删除
E element()
E peek()

这三个都会抛出异常
不会抛出异常

这些我们根据源码得到理解,附上一段源码,理解一下

/**
* Retrieves, but does not remove, the head of this queue. This method
* differs from {@link #peek peek} only in that it throws an exception
* if this queue is empty.
*
* @return the head of this queue
* @throws NoSuchElementException if this queue is empty
*/
E element(); // 上面是对element 的描述

/**
* Retrieves, but does not remove, the head of this queue,
* or returns {@code null} if this queue is empty.
*
* @return the head of this queue, or {@code null} if this queue is empty
*/
E peek(); // 上面是对peek 的描述

简单的实现方法:

public class queue {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
// 二种添加方法 向尾部添加
queue.add("I am first means ");
queue.offer("I am second means");
// 二种取出但不删除 从头部取出 所以每次都是头部信息
String s1 = queue.element();
String s2 = queue.peek();
System.out.println(s1 + "\n" + s2);
// 二种取出删除方法, 从头部删除
queue.remove();
queue.poll();
// 获取长度 全删掉了 没了
System.out.println(queue.size());
}
}

优先队列PriorityQueue:

之前使用的Queue队列。他是严格规定 “先进先出” 的规则,没有优先权限, 这会影响我们一些实际开发, 比如存在VIP用户的基础上, 我们就需要使用PriorityQueue 优先队列,来处理这件事情了。

先来看看一个简单的队列方法:

public class Main {
public static void main(String[] args) {
Queue<String> q = new PriorityQueue<>();
// 添加3个元素到队列:
q.offer("apple");
q.offer("pear");
q.offer("banana");
System.out.println(q.poll()); // apple
System.out.println(q.poll()); // banana
System.out.println(q.poll()); // pear
System.out.println(q.poll()); // null,因为队列为空
}
}
// 默认String类实现了 Comparable 接口, 排序默认升序

那如果我们放入的元素没有实现 Comparable接口呢,PriorityQueue 允许我们提供一个 comparator 对象来判断优先级,这里有一个例子:

package listTest;

import java.util.*;

public class queue {
public static void main(String[] args) {
Queue<User> q = new PriorityQueue<>(new UserComparator());
// 添加3个元素到队列:
q.offer(new User("Bob", "A10"));
q.offer(new User("Alice", "A2"));
q.offer(new User("lucy", "A6"));
q.offer(new User("Boss", "V1"));
System.out.println(q.poll());
System.out.println(q.poll());
System.out.println(q.poll());
System.out.println(q.poll());
System.out.println(q.size());

}
}

class UserComparator implements Comparator<User> {
@Override
public int compare(User u1, User u2) {
if (u1.number.charAt(0) == u2.number.charAt(0)) {
// 如果两人的号都是A开头或者都是V开头,比较号的大小:
if (u1.number.length() == u2.number.length()) {
return u1.number.compareTo(u2.number);
} else {
return (u1.number.length() > u2.number.length() ? 1 : -1); // 如果长度不相同 返回小号
}
}
if (u1.number.charAt(0) == 'V') {
return -1;
// u1的号码是V开头,优先级高:
} else {
return 1;
}
}
}

class User {
public final String name;
public final String number;

public User(String name, String number) {
this.name = name;
this.number = number;
}

@Override
public String toString() {
return "现在是客户:" + name + "// 权限为:" + number;
}
}

小提示:

PriorityQueue实现了一个优先队列:从队首获取元素时,总是获取优先级最高的元素。

PriorityQueue默认按元素比较的顺序排序(必须实现Comparable接口),也可以通过Comparator自定义排序算法(元素就不必实现Comparable接口)。

双向队列 Deque:

不管是Queue队列,还是PriorityQueue 优先队列, 他们都遵循一个原则, 只能从尾部向队列进行增加,从头部取出元素,但是我们可以从Queue中派生出一个 Deque 双向队列,它可以允许我们从二端添加元素,并且可以从二段取出元素。

可以看一下Deque的简单使用:


public static void main(String[] args) {
Deque<String> deque = new LinkedList<>();
// 向二头加入元素
deque.offerFirst("first");
deque.offerLast("last");
// 向二头删除元素
System.out.println(deque.pollFirst());
System.out.println(deque.pollLast());
// 队列长度
System.out.println(deque.size());

}

我们来看一下 Deque 和 Queue的 一些区别:

Means Queue Deque

添加元素到队尾
add(E e) / offer(E e)
addLast(E e) / offerLast(E e)

取队首元素并删除
E remove() / E poll()
E removeFirst() / E pollFirst()

取队首元素但不删除
E element() / E peek()
E getFirst() / E peekFirst()

添加元素到队首

addFirst(E e) / offerFirst(E e)

取队尾元素并删除

E removeLast() / E pollLast()

取队尾元素但不删除

E getLast() / E peekLast()

Collections类:

Collections 给我们提供了一些方法. 比如对集合的排序,扰乱等。

排序

public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("apple");
list.add("pear");
list.add("orange");
// 排序方法
Collections.sort(list);
// 排序后:
System.out.println(list);
}
}

提到排序,这里需要继续排序扩展,一般我们使用的是Arrays.sort() 对数组进行排序, 但是这个排序默认升序, 如果需要进行改写排序规则,怎么办呢?

第一种 使用 Collections.reverseOrder() 方法


public static void main(String[] args) {
Integer[] mylist = {2, 10, 4, 1, 3, 5};
Arrays.sort(mylist, Collections.reverseOrder());
System.out.println(Arrays.toString(mylist));

}

第二种 重写 Comparator接口中的compare方法

   public static void main(String[] args) {
Integer[] mylist = {2, 10, 4, 1, 3, 5};
// 创建一个Comparator 类
Comparator cmp = new CMP();
Arrays.sort(mylist, cmp);
System.out.println(Arrays.toString(mylist));
}

}

class CMP implements Comparator<Integer> {

@Override
public int compare(Integer o1, Integer o2) {
return o1 > o2 ? -1 : 1;
}
}

洗牌打乱

Collections 提供了一个 洗牌算法 shuffle() 可以把集合类的顺序随机打乱。 如下:

public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i=0; i<10; i++) {
list.add(i);
}
// shuffle 算法之后
Collections.shuffle(list);
// 洗牌后:
System.out.println(list);
}
}

本篇文章是一个学习java的笔记,概括集合中的 list ,Arraylist, HashMap, EnumMap, TreeMap, Properties, Set, Queue , PriorityQueue, Deque, Collections 的基本用法, 以及集合的各种重写方法手段,当个字典吧!

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

二万长文,概括Java中集合的大致用法, 做个字典就行!

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » 二万长文,概括Java中集合的大致用法, 做个字典就行!
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏