Java:常用的容器小记
Java:常用的容器小记
对 Java 中的 常用容器,做一个微不足道的小小小小记
容器类概述
常见容器主要包括 Collection 和 Map 两种,Collection 存储着对象的集合,而 Map 存储着键值对(两个对象)的映射表。
Collection
Set
Set | 说明 |
---|---|
TreeSet | 基于红黑树实现,支持有序性操作; 例如:根据一个范围查找元素的操作。 但是查找效率不如 HashSet,HashSet 查找的时间复杂度为 O(1),TreeSet 则为 O(logN) |
HashSet | 基于哈希表(HashMap)实现,支持快速查找,但不支持有序性操作。 并且失去了元素的插入顺序信息,也就是说使用 Iterator 遍历 HashSet 得到的结果是不确定的 |
LinkedHashSet | 具有 HashSet 的查找效率,底层是链表+哈希表。 使用哈希表存储元素,再维护一个双向链表保存元素的插入信息 |
List
List | 说明 |
---|---|
ArrayList | 基于动态数组实现,支持随机访问 |
Vector | 和 ArrayList 类似,但它是线程安全的 |
LinkedList | 基于双向链表实现,只能顺序访问,但是可以快速地在链表中间插入和删除元素。 不仅如此,LinkedList 还可以用作栈、队列和双向队列 |
Queue
Queue | 说明 |
---|---|
LinkedList | 基于链表实现的队列,可以用它来实现双向队列 |
PriorityQueue | 基于堆结构实现,可以用它来实现优先队列 |
ArrayDeque | 实现了Deque(双向队列),Deque继承自Queue 使用了可变数组,可以做为队列来使用,也可以作为栈使用 ArrayDeque不支持 null 值 |
Map
Map | 说明 |
---|---|
TreeMap | 基于红黑树实现 |
HashMap | 基于哈希表实现 |
HashTable | 和 HashMap 类似,但它是线程安全的,这意味着同一时刻多个线程可以同时写入 HashTable 并且不会导致数据不一致。 它是遗留类,不应该去使用它。 现在可以使用 ConcurrentHashMap 来支持线程安全,并且 ConcurrentHashMap 的效率会更高,因为 ConcurrentHashMap 引入了分段锁 |
LinkedHashMap | 使用双向链表来维护元素的顺序,顺序为插入顺序或者最近最少使用(LRU,Least Recently Used)顺序 |
List & Set & Map
List & Set & Map 之间的大致区别:
比较 | LIst | Set | Map |
---|---|---|---|
继承接口 | Collection | Collection | 是个接口 |
常见实现类 | AbstractList 常用的子类有: ArrayList LinkedList Vector |
AbstractSet 常用的子类有: HashSet LinkedHashSet TreeSet |
实现的类: HashMap HashTable LinkedHashMap |
常见方法 | add() remove() clear() get() contains() size() ... |
add() remove() clear() get() contains() size() ... |
put() get() remove() clear() containsKey() containsValue() keySet() values() size() ... |
元素 | 可重复 | 不可重复 | 不可重复 |
顺序 | 有序 | 一般无序(由hashcode决定) | 一般无序 |
线程安全 | Vector线程安全 | HashTable线程安全 |
Collection & Collections
Collection
是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。List,Set,Queue接口都继承Collection;直接实现该接口的类只有 AbstractCollection 类,该类也只是一个抽象类,提供了对集合类操作的一些基本实现。
Collections
是不属于 Java 的集合框架的,它是集合类的一个工具类/帮助类。此类不能被实例化, 服务于 Java 的 Collection 框架。它包含有关集合操作的静态多态方法,实现对各种集合的搜索、排序、线程安全等操作。
常用功能
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中添加一些元素。public static void shuffle(List<?> list)
打乱顺序 :打乱集合顺序。public static <T> void sort(List<T> list)
:将集合中元素按照默认规则排序。public static <T> void sort(List<T> list,Comparator<? super T> )
:将集合中元素按照指定规则排序。
public class CollectionsDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
// 原来写法
// list.add(12);
// list.add(14);
// list.add(15);
// list.add(1000);
// 采用工具类 完成 往集合中添加元素
Collections.addAll(list, 5, 222, 1,2);
System.out.println(list);
//排序方法
Collections.sort(list);
System.out.println(list);
}
}
// 结果:
// [5, 222, 1, 2]
// [1, 2, 5, 222]
Collections 中的 sort 方法
Comparator比较器
排序方法:public static <T> void sort(List<T> list)
:将集合中元素按照默认规则排序。
如,对字符串类型进行比较:
public class CollectionsDemo2 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("cba");
list.add("aba");
list.add("sba");
list.add("nba");
//排序方法
Collections.sort(list);
System.out.println(list);
}
}
// 结果:
// [aba, cba, nba, sba]
说到排序了,简单的说就是两个对象之间比较大小,那么在 Java 中提供了两种比较实现的方式,一种是比较死板的采用 java.lang.Comparable
接口去实现,一种是灵活的当我需要做排序的时候在去选择的java.util.Comparator
接口完成。
那么我们采用的 public static <T> void sort(List<T> list)
这个方法完成的排序,实际上要求了被排序的类型需要实现 Comparable 接口完成比较的功能,在String类型上如下:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
// 实现了Comparable<String>的方法,该接口内有抽象方法public int compareTo(T o);
// 在String内对其进行了实现
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
}
String 类实现了这个接口,并完成了比较规则的定义,但是这样就把这种规则写死了,那比如我想要字符串按照第一个字符降序排列,那么这样就要修改String的源代码,这是不可能的了。
// 重写排序的规则
@Override
public int compareTo(Person o) {
//return 0; //认为元素都是相同的
//自定义比较的规则, 比较两个人的年龄(this,参数Person)
//return this.getAge() - o.getAge();//年龄升序排序
return o.getAge() - this.getAge();//年龄升序排序
}
那么这个时候我们可以使用 public static <T> void sort(List<T> list,Comparator<? super T> )
方法灵活的完成,这个里面就涉及到了 Comparator这个接口,位于位于 java.util
包下,排序是 comparator 能实现的功能之一,该接口代表一个比较器,比较器具有可比性!顾名思义就是做排序的,通俗地讲需要比较两个对象谁排在前谁排在后,那么比较的方法就是:public int compare(String o1, String o2)
:比较其两个参数的顺序。
两个对象比较的结果有三种:大于,等于,小于。
如果要按照升序排序,则o1 小于o2,返回(负数),相等返回0,01大于02返回(正数);
如果要按照降序排序,则o1 小于o2,返回(正数),相等返回0,01大于02返回(负数)
总结 Comparator 的排序规则: o1-o2 为升序;o2-o1 为降序
操作如下:
public class CollectionsDemo3 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("cba");
list.add("aba");
list.add("sba");
list.add("nba");
//排序方法 按照第一个单词的降序
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.charAt(0) ‐ o1.charAt(0);
}
});
System.out.println(list);
}
}
// 结果如下:
// [sba, nba, cba, aba]
Comparable 与 Comparator 两个接口的区别
Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。只能在类中实现 compareTo()
一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort
(和 Arrays.sort
)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
Comparator:强行对某个对象进行整体排序。可以将 Comparator 传递给 sort 方法(如Collections.sort
或 Arrays.sort
),从而允许在排序顺序上实现精确控制。还可以使用Comparator 来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。
案例说明:
创建一个学生类,存储到ArrayList集合中完成指定排序操作。
- Student 初始类
public class Student{
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.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 String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 测试类:
public class Demo {
public static void main(String[] args) {
// 创建四个学生对象 存储到集合中
ArrayList<Student> list = new ArrayList<Student>();
list.add(new Student("rose",18));
list.add(new Student("jack",16));
list.add(new Student("abc",16));
list.add(new Student("ace",17));
list.add(new Student("mark",16));
/*
让学生 按照年龄排序 升序
*/
Collections.sort(list); //要求 该list中元素类型 必须实现比较器Comparable接口
for (Student student : list) {
System.out.println(student);
}
}
}
发现,当我们调用
Collections.sort()
方法的时候 程序报错了。原因:如果想要集合中的元素完成排序,那么必须要实现比较器 Comparable 接口。
于是我们就完成了Student类的一个实现,如下:
public class Student implements Comparable<Student>{
....
@Override
public int compareTo(Student o) {
return this.age‐o.age;//升序
}
}
再次测试,代码就OK 了效果如下:
Student{name='jack', age=16}
Student{name='abc', age=16}
Student{name='mark', age=16}
Student{name='ace', age=17}
Student{name='rose', age=18}
如果在使用的时候,想要独立的定义规则去使用 可以采用
Collections.sort(List list,Comparetor c)
方式,自己定义规则:Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o2.getAge()‐o1.getAge();//以学生的年龄降序
}
});
效果:
Student{name='rose', age=18}
Student{name='ace', age=17}
Student{name='jack', age=16}
Student{name='abc', age=16}
Student{name='mark', age=16}
如果想要规则更多一些,可以参考下面代码:
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// 年龄降序
int result = o2.getAge()‐o1.getAge();//年龄降序
if(result==0){//第一个规则判断完了 下一个规则 姓名的首字母 升序
result = o1.getName().charAt(0)‐o2.getName().charAt(0);
}
return result;
}
});
效果如下:
Student{name='rose', age=18}
Student{name='ace', age=17}
Student{name='abc', age=16}
Student{name='jack', age=16}
Student{name='mark', age=16}
参考
https://mp.weixin.qq.com/s/q1r9Pno6ANUzZ9wMzA-JSg
https://blog.csdn.net/qq_41701956/article/details/103223461
Java:常用的容器小记的更多相关文章
- <转>Java 常用排序算法小记
排序算法很多地方都会用到,近期又重新看了一遍算法,并自己简单地实现了一遍,特此记录下来,为以后复习留点材料. 废话不多说,下面逐一看看经典的排序算法: 1. 选择排序 选择排序的基本思想是遍历数组的过 ...
- Java:TreeMap类小记
Java:TreeMap类小记 对 Java 中的 TreeMap类,做一个微不足道的小小小小记 概述 前言:之前已经小小分析了一波 HashMap类.HashTable类.ConcurrentHas ...
- Java 文件句柄泄露问题解决小记(转)
转:Java 文件句柄泄露问题解决小记 维护 WebIDE 免不了要管理很多的文件, 自从我们线上系统增加了资源回收功能,便一直受一个问题困扰:后台线程解绑目录时偶尔报错,看症状因为是某些文件被占用了 ...
- Java:HashMap类小记
Java:HashMap类小记 对 Java 中的 HashMap类,做一个微不足道的小小小小记 概述 HashMap:存储数据采用的哈希表结构,元素的存取顺序不能保证一致.由于要保证键的唯一.不重复 ...
- java常用英文解释
java常用名词解释: OO: object-oriented ,面向对象 OOP:object-oriented programming,面向对象编程 Author:JCC Object:对象JDK ...
- Java常用jar包用途
Java常用jar包用途: USAGE INDEX JAR NAME USAGE 1 ASM asm-2.2.3.jar ASM字节码库 2 ASM asm-commons-2.2.3.jar ASM ...
- JAVA常用数据结构及原理分析
JAVA常用数据结构及原理分析 http://www.2cto.com/kf/201506/412305.html 前不久面试官让我说一下怎么理解java数据结构框架,之前也看过部分源码,balaba ...
- java中的容器问题
小小的总结一下java中的容器问题. 一.三个知识点 1.迭代器 1).java.util.Interator + hasnext(); next(); remove(); 2).java.lang. ...
- JAVA常用知识点及面试题总结
1. String.StringBuffer.StringBuilder三者区别? (1)三者在执行速率上的比较: String<StringBuffer<StringBuilder 原因 ...
随机推荐
- windows 安装pip 及更换pip国内源
一.官网下载压缩包并解压. 官网:https://pypi.org/project/pip/#files 文件:选择.tar.gz版本 image 解压后,进入解压文件目录,在当前路径下打开cmd窗口 ...
- 在C#中使用RSA进行加密和解密
这篇文章向您展示了如何在c#.net Windows窗体应用程序中使用RSA算法对字符串进行加密和解密.RSA是由Ron Rivest,Adi Shamir和Leonard Adleman开发的非对称 ...
- vue实现拖动div元素
html: <div id="app1"> <div v-drag class="drag"></div> <div ...
- 使用AOP+自定义注解完成spring boot的接口权限校验
记使用AOP+自定义注解完成接口的权限校验,代码如下: pom文件添加所需依赖: 1 <dependency> 2 <groupId>org.aspectj</group ...
- Nginx优化与防盗链
目录: 一.隐藏版本号 二.修改用户与组 三.缓存时间 四.日志切割 五.连接超时 六.更改进程数 七.配置网页压缩 一.隐藏版本号 可以使用 Fiddler 工具抓取数据包,查看 Nginx版本 也 ...
- DataGridView高度自动调整
AutoResizeGrid.cs代码 /// <summary> /// 根据行数据,自动调整DataGridView高度 /// </summary> public sea ...
- 计算字符串的长度.len,RuneCountInString
内置函数len(),可以返回字符串/数组/切片/map/channel的长度. unicode/utf8包 函数:RuneCountInString(输入一个字符串),返回int类型的字符串长度.由于 ...
- 一文看懂String类中的常用方法
1.int length(): 返回字符串的长度: return value.length 2.char charAt(int index): 返回某索引处的字符return value[index] ...
- 2.1Java基础
2.1.9面向对象的三大特性(携程): 封装:把一个对象的属性隐藏在对象内部,外部对象不能直接访问这个对象的内部信息.但是可以提供一些可以被外界访问的方法来操作属性.就比如我们常常创建一个类,把他的属 ...
- Java数学函数的使用
Java的Math类中提供了一系列关于数学运算的静态方法,常见的运算整理如下[1] 算数运算 Math.sqrt() // 平方根 Math.cbrt() // 立方根 Math.pow(a, b) ...