Java 学习笔记 - 集合,985 研究生被小公司领导留了 3 年
}
}
package study.gather.Demo01;
import java.util.ArrayList;
import java.util.Collection;
public class Demo02 {
public static void main(String[] args) {
//新建collection对象 和 学生对象
Collection collection = new ArrayList();
Student s1 = new Student("张三", 20);
Student s2 = new Student("李四", 25);
Student s3 = new Student("王五", 24);
//添加数据
collection.add(s1);
collection.add(s2);
collection.add(s3);
System.out.println("元素个数:"+collection.size());
System.out.println(collection.toString());
//删除
collection.remove(s1);
System.out.println("元素个数:"+collection.size());
//清空
collection.clear();//只是在将对象在集合里移除了 但是对象并没有消失
}
}
### []( )重写equals方法
如何正确编写equals()方法?equals()方法要求我们必须满足以下条件:
* 自反性(Reflexive):对于非null的x来说,x.equals(x)必须返回true;
* 对称性(Symmetric):对于非null的x和y来说,如果x.equals(y)为true,则y.equals(x)也必须为true;
* 传递性(Transitive):对于非null的x、y和z来说,如果x.equals(y)为true,y.equals(z)也为true,那么x.equals(z)也必须为true;
* 一致性(Consistent):对于非null的x和y来说,只要x和y状态不变,则x.equals(y)总是一致地返回true或者false;
* 对null的比较:即x.equals(null)永远返回false。
我们总结一下equals()方法的正确编写方法:
* 先确定实例“相等”的逻辑,即哪些字段相等,就认为实例相等;
* 用`instanceof`判断传入的待比较的`Object`是不是当前类型,如果是,继续比较,否则,返回`false`;
* 对引用类型用`Objects.equals()`比较,对基本类型直接用==比较。
* 使用`Objects.equals()`比较两个引用类型是否相等的目的是省去了判断`null`的麻烦。两个引用类型都是`null`时它们也是相等的。
* 如果不调用`List`的`contains()`、`indexOf()`这些方法,那么放入的元素就不需要实现`equals()`方法。
示例代码:
import java.util.List;
import java.util.Objects;
public class HelloWord {
public static void main(String[] args) {
List<Person> list = List.of(
new Person("Xiao", "Ming", 18),
new Person("Xiao", "Hong", 25),
new Person("Bob", "Smith", 20)
);
boolean exist = list.contains(new Person("Bob", "Smith", 20));
System.out.println(exist ? "测试成功!" : "测试失败!");
}
}
class Person {
String firstName;
String lastName;
int age;
public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(firstName, person.firstName) && Objects.equals(lastName, person.lastName);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName, age);
}
}
[]( )List
--------------------------------------------------------------
在集合类中,`List`是最基础的一种集合:它是一种`有序列表`。
`List`的行为和数组几乎完全相同:List内部按照放入元素的先后顺序存放,每个元素都可以通过索引确定自己的位置,`List`的索引和数组一样,从`0`开始。
### []( )ArrayList
![在这里插入图片描述](https://static001.geekbang.org/infoq/69/6921869cb3865851a1387b6ac3f8b5cc.png)
引用包:
import java.util.ArrayList;
创建方法:
ArrayList<T> arrayList = new ArrayList<T>();
示例代码:
import java.util.ArrayList;
import java.util.Comparator;
public class RunoobTest {
public static void main(String[] args) {
ArrayList<String> sites = new ArrayList<String>();
//添加元素
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Weibo");
System.out.println(sites);
//访问元素
System.out.println(sites.get(1)); // 访问第二个元素
//修改元素
sites.set(2, "Wiki"); // 第一个参数为索引位置,第二个为要修改的值
System.out.println(sites);
//删除元素
sites.remove(3); // 删除第四个元素
System.out.println(sites);
//获取List长度
System.out.println(sites.size());
//循环输出元素
for (int i = 0; i < sites.size(); i++) {
System.out.println(sites.get(i));
}
for (String i : sites) {
System.out.println(i);
}
//List排序
sites.sort(Comparator.naturalOrder());
System.out.println("排序后: " + sites);
}
}
List转Array:
import java.util.List;
public class HelloWord {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
//第1种方法
Object[] array = list.toArray();
for (Object s : array) {
System.out.println(s);
}
//第2种方法,指定类型
String[] stringArray1 = list.toArray(new String[3]);
for (String n : stringArray1) {
System.out.println(n);
}
//第2种方法改进版
String[] stringArray2= list.toArray(new String[list.size()]);
for (String n : stringArray2) {
System.out.println(n);
}
//第3种方法
String[] stringArray3 = list.toArray(String[]::new);
for (String n : stringArray3) {
System.out.println(n);
}
}
}
Array变List
import java.util.List;
public class HelloWord {
public static void main(String[] args) {
//Array变为List就简单多了,通过List.of(T...)方法
List<Integer> list = List.of(12, 34, 56);
System.out.println(list);
//我们调用List.of(),它返回的是一个只读List,如下代码会报错
list.add(999); // UnsupportedOperationException
}
}
常用API:
| 方法 | 描述 |
| --- | --- |
| add() | 将元素插入到指定位置的 arraylist 中 |
| addAll() | 添加集合中的所有元素到 arraylist 中 |
| clear() | 删除 arraylist 中的所有元素 |
| clone() | 复制一份 arraylist |
| contains() | 判断元素是否在 arraylist |
| get() | 通过索引值获取 arraylist 中的元素 |
| indexOf() | 返回 arraylist 中元素的索引值 |
| removeAll() | 删除存在于指定集合中的 arraylist 里的所有元素 |
| remove() | 删除 arraylist 里的单个元素 |
| size() | 返回 arraylist 里元素数量 |
| isEmpty() | 判断 arraylist 是否为空 |
| subList() | 截取部分 arraylist 的元素 |
| set() | 替换 arraylist 中指定索引的元素 |
| sort() | 对 arraylist 元素进行排序 |
| toArray() | 将 arraylist 转换为数组 |
| toString() | 将 arraylist 转换为字符串 |
| ensureCapacity() | 设置指定容量大小的 arraylist |
| lastIndexOf() | 返回指定元素在 arraylist 中最后一次出现的位置 |
| retainAll() | 保留 arraylist 中在指定集合中也存在的那些元素 |
| containsAll() | 查看 arraylist 是否包含指定集合中的所有元素 |
| trimToSize() | 将 arraylist 中的容量调整为数组中的元素个数 |
| removeRange() | 删除 arraylist 中指定索引之间存在的元素 |
| replaceAll() | 将给定的操作内容替换掉数组中每一个元素 |
| removeIf() | 删除所有满足特定条件的 arraylist 元素 |
| forEach() | 遍历 arraylist 中每一个元素并执行特定操作 |
小结:
1. ArrayList必须要连续空间,查询快、增删慢
2. 频繁访问列表中的某一个元素时使用ArrayList。
3. 只需要在列表末尾进行添加和删除元素操作时使用ArrayList。
### []( )LinkedList
链表(`Linked list`)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。链表可分为单向链表和双向链表。
一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。
![在这里插入图片描述](https://static001.geekbang.org/infoq/d7/d75e05d084f0265fed0a84ab0778b7c9.png)
一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。
![在这里插入图片描述](https://static001.geekbang.org/infoq/97/97618990540ac28ce512d4c431795169.png)
以下情况使用 LinkedList :
* 你需要通过循环迭代来访问列表中的某些元素。
* 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
LinkedList 继承了 `AbstractSequentialList` 类。
LinkedList 实现了 `Queue` 接口,可作为队列使用。
LinkedList 实现了 `List` 接口,可进行列表的相关操作。
LinkedList 实现了 `Deque` 接口,可作为队列使用。
LinkedList 实现了 `Cloneable` 接口,可实现克隆。
LinkedList 实现了 `java.io.Serializable` 接口,即可支持序列化,能通过序列化去传输
![在这里插入图片描述](https://static001.geekbang.org/infoq/3e/3eaac99185a70d60ae9493b1f641fbcf.png)
引用包:`import java.util.LinkedList;`
创建方法:
LinkedList<E> list = new LinkedList<E>(); // 普通创建方法
或者
LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表
示例代码:
import java.util.LinkedList;
public class HelloWord {
public static void main(String[] args) {
LinkedList<String> sites = new LinkedList<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Weibo");
// 使用 addFirst() 在头部添加元素
sites.addFirst("Baidu");
// 使用 addLast() 在尾部添加元素
sites.addLast("Alibaba");
for (int size = sites.size(), i = 0; i < size; i++) {
System.out.println(sites.get(i));
}
// 使用 removeFirst() 移除头部元素
sites.removeFirst();
// 使用 removeLast() 移除尾部元素
sites.removeLast();
for (String i : sites) {
System.out.println(i);
}
// 使用 getFirst() 获取头部元素
System.out.println(sites.getFirst());
// 使用 getLast() 获取尾部元素
System.out.println(sites.getLast());
}
}
常用方法:[传送门]( )
小结:
1. API
1. 首尾添加
2. 首尾获取
3. 首尾移除
2. (双向)链表结构:
1. 每一个元素都分为上一个,下一个,当前元素
2. 每次增加元素,只新增一个对象,极大提高了集合元素变化的性能
3. 对元素的访问性能不高,因为其本质是没有游标的,要访问某个元素都是从首尾开始迭代
[]( )Set
-------------------------------------------------------------
如果我们`只需要存储不重复的key`,并不需要存储映射的value,那么就可以使用`Set`。
特点:
* 无序、无下标、元素不可重复
* Set实现了Collection接口中定义的方法。
Set用于存储`不重复`(唯一)的元素集合,它主要提供以下几个方法:
* 将元素添加进Set:boolean `add`(E e)
* 将元素从Set删除:boolean `remove`(Object e)
* 判断是否包含元素:boolean `contains`(Object e)
Set实际上相当于只存储key、不存储value的Map。我们经常用Set用于去除重复元素。
![在这里插入图片描述](https://static001.geekbang.org/infoq/5d/5d2b4a361a694059d2aad3f5b83eb1cb.png)
Set接口并不保证有序,而SortedSet接口则保证元素是有序的:
* `HashSet`是无序的,因为它实现了`Set`接口,并没有实现`SortedSet`接口;
* `TreeSet`是有序的,因为它实现了`SortedSet`接口。
### []( )HashSet
没有真正意义上的set集合,他使用的是`HashMap`的key。
方法:
* 新建集合 `HashSet<String> hashSet = new HashSet<String>();`
* 添加元素 `hashSet.add( );`
* 删除元素 `hashSet.remove( );`
* 遍历操作
增强for `for(type type : hashSet)`
迭代器 `Iterator<String> it = hashSet.iterator( );`
* 判断 `hashSet.contains( );`, `hashSet.isEmpty();`
### []( )TreeSet
特点:
* 基于排列顺序实现元素不重复
* 实现`SortedSet`接口,对集合元素自动排序
* 元素对象的类型必须实现`Comparable`接口,指定排序规则
* 通过`CompareTo`方法确定是否为重复元素
* 使用TreeSet和使用TreeMap的要求一样,添加的元素必须正确实现`Comparable`接口,如果没有实现`Comparable`接口,那么创建TreeSet时必须传入一个`Comparator`对象。
方法:
* 创建集合 TreeSet treeSet = new TreeSet<>()
* 添加元素 treeSet.add();
* 删除元素 treeSet.remove();
* 遍历 1. 增强for 2. 迭代器
* 判断 treeSet.contains();
使用:要求:元素必须实现`Comparable`接口,`compareTo()`方法的返回值为0,认为是重复元素
// 重写 compareTo
@override
public int compareTo(Person o){
int n1 = this.getName().compareTo(o.getName()); //后面的 compareTo 方法为 String 带的方法
int n2 = this.getAge()-o.getAge();
return n1 == 0 ? n2 : n1;
}
或者 传入一个`Comparator`对象
// 重写 compare 创建集合时就制定比较规则
TreeSet<Person> treeSet = new TreeSet<>(new Comparator<Person>){
@override
public int compare(Person o1,Person o2){
int n1 = o1.getName().compareTo(o2.getName());
int n2 = o1.getAge()-o2.getAge();
return n1 == 0 ? n2 : n1;
最后
本人也收藏了一份 Java 面试核心知识点来应付面试,借着这次机会可以免费送给我的读者朋友们:
目录:
Java 面试核心知识点
一共有 30 个专题,足够读者朋友们应付面试啦,也节省朋友们去到处搜刮资料自己整理的时间!
Java 面试核心知识点
资料的领取方式:点赞后【戳面试资料】即可免费获取哦!
程序猿一枚
VX:vip204888 领取资料 2021.07.29 加入
还未添加个人简介
评论