本篇主要是集合框架基础和List集合,Map集合等等后续更
集合
- 14.1 集合框架
- 14.1.1 概念
- 14.1.2 集合架构
- 14.2 Collection接口
- 14.2.1 常用方法
- 14.3 迭代器
- 14.3.1 迭代器原理
- 14.3.2 迭代器使用常见问题
- 14.4 泛型基本使用
- 14.5 ArrayList类
- 14.5.1 常用方法
- 14.5.2 实现原理
- 14.6 LinkedList类
- 14.6.1 常用方法
- 14.6.2 LinkedList实现原理
- 14.6.3 堆栈和队列结构
- 14.7 Vector类
- 14.7.1 常用方法
- 14.7.2 实现原理
- 14.7.3 常见面试问题
- 14.8 HashSet类
- 14.8.1 HashSet基本使用
- 14.8.2 HashSet 去重原理
- 14.9 LinkedHashSet类
- 14.10 Collections工具类
14.1 集合框架
- 什么是集合框架?
Java中的集合框架其实就是对**【数据结构】**的封装,这个封装中提供了一些常用方法,可方便操作数据,无需程序猿自定定义操作,只需要调用封装方法就可以完成对存在集合中数据【增删改查】
集合其实就是对数据结构一种封装,所以之前sun公司就把集合放置到一个统一包中进行管理【java.util】包
- 什么是数据结构?
数据结构其实就是计算机,组织和存储数据形式
数据结构是指相互之间存在一种或多种特定关系的数据集合
通常情况下,精心选择数据结构可以带来更加高效运行和存储效率, 数据结构往往高效的原因在于**【检索算法】和【索引计数】**
常见数据结构:【数组、栈、链表(单向和双向)、哈希表、队列(单向和双向)、堆、树、图】
Java的集合框架其实就是对【数据结构实现】,我们需要掌握就是如何操作这个数据结构(即操作集合中方法),高效存储与处理数据
PS:根据不同数据结构,操作数据性能是不同(有地查询块、有的插入快、有地允许重复、有的不允许重复等等),在开发中只要选择合理数据结构即集合对数据存储与操作即可
-
Java中常见的集合框架
习惯性说Java中集合有三大框架【List、Set和Map】
如果详细说明的话应该2个框架3个实现
- 2个框架: Collection 和 Map
- 3个实现 :Collection这个集合下两个主要实现 List 和 set 所以称为三大集合List、set 和Map
-
集合和数组最大区别在于:
- 集合中只能储存引用类型即对象
- 集合是一个变长容量,根据集合储存元素个数动态进行删减【扩容和减容】
- 数组是一个定长容器,创建大小数固定,无论存储多少数据长度都是唯一
常见三大集合框架:
- List【列表】:集合中存储对象是按照索引位置进行存储,允许存储重复数据
- Set【集】: 集合中存储对象不是按照特定方式进行存储,不允许出现重复数据
- Map【映射】:集合中每一个存储元素都是以一种【键值对key- value】方式进行存储的,以一种key和value的形式存储的,key 这个对象是不允许重复【唯一性】,value是允许重复
14.1.1 概念
- 集合是一种对象容器,用于存放对象
- 数组的缺点:
- 1、数组定长,一旦定义不能改变
- 2、数组中没有方法
- 3、数组中只能存放相同的数据类型的数据
- 集合特点:
- 1、长度可以改变
- 2、集合中丰富的操作元素的方法
- 3、集合中只能存储引用数据类型的数据
- 集合的分类
- 1、单列集合 (集合中一个元素保存一个数据) Collection
- 2、双列集合 (集合中一个元素保存两个数据) Map
14.1.2 集合架构
集合架构 |
---|
14.2 Collection接口
单列集合的顶层接口
14.2.1 常用方法
- add方法向集合集合中添加元素
- clear方法,清空集合中所有元素
- contains方法 判断集合是否包含某个元素
- isEmpty判断集合是否为空
- remove方法 移除集合中元素,返回boolean类型。如果集合中不包含次元素,则删除失败
- size()返回集合中元素的个数
- toArray将集合转换成数组。
- addAll 向一个集合中添加另一个集合
- containsAll 判断一个集合中是否包含另一个集合
- removeAll 从一个集合中移除另一个集合
public class CollectionDemo {
public static void main(String[] args) {
//创建Collection对象
Collection coll = new ArrayList();
//Collection接口下常用的方法
//add 向集合中添加元素
coll.add("jack");
coll.add(10);
coll.add("rose");
System.out.println(coll);
//contains 判断集合中是否包含指定元素
System.out.println(coll.contains("赵四"));
//isEmpty 判断集合的元素个数是否为0
System.out.println(coll.isEmpty());
//remove 移除集合中指定的元素,如果存在返回true、否则返回false
coll.remove("jack1");
System.out.println(coll);
//size 获取集合中元素个数
System.out.println(coll.size());
//toArray 将集合变成数组
Object[] arr = coll.toArray();
//Arrays.toString 将数组变成字符串形式
System.out.println(Arrays.toString(arr));
int[] nums = {1,2,3,4};
//将数组转成集合
List asList = Arrays.asList(nums);
System.out.println(asList);
Collection coll1 = new ArrayList();
coll1.add("lilei");
coll1.add("hanmeimei");
//addAll 将另一个集合中元素添加到当前集合中
coll1.addAll(coll);
System.out.println(coll1);
//containsAll 判断集合中是否包含另一个集合
System.out.println(coll1.containsAll(coll));
// coll1.removeAll(coll);
// System.out.println(coll1);
//retainAll 保留coll中包含的元素
coll1.retainAll(coll);
System.out.println(coll1);
}
}
14.3 迭代器
14.3.1 迭代器原理
迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。
迭代器原理 |
---|
//迭代器的作用:获取集合中的所有的元素
Collection coll = new ArrayList();
coll.add("jack");
coll.add("rose");
coll.add(10);
coll.add(20.2);
//1、获取迭代器对象
Iterator it = coll.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
System.out.println(coll);
14.3.2 迭代器使用常见问题
- 1、迭代器迭代完成之后,迭代器的位置在最后一位。 所以迭代器只能迭代一次
- 2、迭代器在迭代的时候,不要调用多次next方法,可能会出错 NoSuchElementException
- 3、在迭代器迭代的时候,不能向集合中添加或者删除元素 ConcurrentModificationException
public class IteratorDemo {
public static void main(String[] args) {
//使用迭代器需要注意的问题
//1、迭代器只能使用一次
// Collection coll = new ArrayList();
// coll.add("jack");
// coll.add("rose");
// coll.add(10);
// coll.add(20.2);
// Iterator it = coll.iterator();
// while(it.hasNext()){
// System.out.println(it.next());
// }
// while(it.hasNext()){
// System.out.println(it.next());
// }
//2、迭代器使用的时候不能多次使用next方法
// Collection coll = new ArrayList();
// coll.add("jack");
// coll.add("rose");
// coll.add(10);
// coll.add(20.2);
// coll.add(100);
// Iterator it = coll.iterator();
// while(it.hasNext()) {
// Object obj = it.next();
// System.out.println(it.next());
// }
//3、迭代器在迭代的时候不要添加或者删除元素
Collection coll = new ArrayList();
coll.add("jack");
coll.add("rose");
coll.add(10);
coll.add(20.2);
coll.add(100);
Iterator it = coll.iterator();
while(it.hasNext()) {
coll.remove(10);
//coll.add("zhaosi");
System.out.println(it.next());
}
}
}
14.4 泛型基本使用
泛型:参数化类型 JDK1.5之后
- 用途:
- 因为如果不使用泛型,那么向集合中添加元素,实际当做Object对象传递进去的,此时发生向上转型了当从集合中获取数据,得到的是Object类型,那么在使用的需要向下转型,才能正常使用。因此频繁向上向下转型。可能会出现类转换异常。 这个时候就需要使用泛型。
- 泛型的作用实际上就是讲类型转换的检查提前到了编译期
- 泛型擦除: JDK1.7之后
- 集合类型<泛型> 变量名 = new 集合类型<>();
- 泛型需要注意的问题:
- 1、泛型上不存在多态
- Collection coll = new ArrayList();//错误
- 2、泛型只能是引用数据类型
- 如果是基本数据类型,则使用它的包装类
public class GenericDemo {
public static void main(String[] args) {
// Collection coll = new ArrayList();
// coll.add(new Student("我要去输液了",38));
// coll.add(new Student("要输什么液",20));
// coll.add(new Teacher("想你的夜",30));
// coll.add("哈哈哈~~平衡了");
// //获取迭代器对象
// Iterator it = coll.iterator();
// while(it.hasNext()) {
// Student stu = (Student) it.next();
// stu.play();
// }
// Collection<Student> coll = new ArrayList<>();
// coll.add(new Student("我要去输液了",38));
// //coll.add(""); 不能添加其他类型的元素
// coll.add(new Student("我要去输液了",38));
// //获取迭代器对象
// Iterator<Student> it = coll.iterator();
// while(it.hasNext()) {
// Student stu = it.next();
// stu.play();
// }
// Collection<Person> coll = new ArrayList<Person>();
// coll.add(new Student("我要去输液了",38));
// Collection<Integer> coll = new ArrayList<Integer>();
}
}
class Person{
}
class Teacher extends Person{
String name;
int age;
public Teacher() {
}
public Teacher(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
class Student extends Person{
String name;
int age;
public Student() {
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void play() {
System.out.println("就是玩儿");
}
}
14.5 ArrayList类
14.5.1 常用方法
- add(int index, E element)
- remove(int index)
- set(int index, E element)
- get(int index)
- subList(int beginIndex,int endIndex)
- list.listIterator();
package com.qf.demo02;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class ArrayListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
//List集合相对于Collection集合多了一些关于下标操作的方法
//List集合的常用方法
list.add("jack");
list.add("rose");
list.add("cxk");
list.add("尼古拉斯");
System.out.println(list);
System.out.println("======================================");
//在集合指定下标位置上添加元素 add(index, element)
list.add(0, "李雷");
list.add(3, "韩梅梅");
list.add(6, "亚洲舞王");
//list.add(10, "赵四"); 下标范围:0~size
System.out.println(list);
System.out.println("======================================");
//清空集合中所有的元素 clear()
//list.clear();
//System.out.println(list);
System.out.println("======================================");
//返回元素在集合中的下标,如果不存在返回-1
System.out.println(list.indexOf("cxk"));
//返回元素在集合中的下标(找到集合中最后一个相同元素),如果不存在返回-1
System.out.println(list.lastIndexOf("cxk"));
System.out.println("======================================");
//移除集合中指定下标位置上的元素 下标范围:0 ~ size-1
list.remove(0);
System.out.println(list);
System.out.println("======================================");
//修改集合中指定下标位置上的元素 下标范围:0 ~ size-1
list.set(1, "李雷");
System.out.println(list);
System.out.println("======================================");
//截取集合中指定下标开始到结束位置上的元素
List<String> list1 = list.subList(2, 5);
System.out.println("list1----》"+list1);
System.out.println("======================================");
//获取指定下标位置上的元素
System.out.println(list.get(0));
/**
* List集合遍历的三种方式:
* 1、迭代器
* 2、for循环
* 3、foreach循环(增强for循环) 可以遍历数组和集合
*
* 语法:
* for(元素的类型 变量 : 数组|集合){ //变量就表示遍历出来的元素
*
* }
*/
System.out.println("===================迭代器遍历===================");
Iterator<String> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
System.out.println("===================for循环遍历===================");
for (int i = 0; i < list.size() ; i++) {
System.out.println(list.get(i));
}
System.out.println("===================foreach循环遍历===================");
for(String s : list) {
System.out.println(s);
}
System.out.println("=================list集合的迭代器=====================");
ListIterator<String> li = list.listIterator();
// while(li.hasNext()) {
// System.out.println(li.next());
// }
//
// while(li.hasPrevious()) {
// System.out.println(li.previous());
// }
while(li.hasNext()) {
li.add("hehe");
System.out.println(li.next());
}
System.out.println("--------------");
while(li.hasPrevious()) {
System.out.println(li.previous());
}
}
}
14.5.2 实现原理
ArrayList其底层实现使用数组
实现原理 |
---|
14.6 LinkedList类
14.6.1 常用方法
常用的方法与ArrayList一致。自己独有一些向首尾添加移除等方法(可以模拟对列、堆栈等数据结构)
package com.qf.demo02;
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
//创建LinkedList对象
LinkedList<String> list = new LinkedList<String>();
list.add("jack");
list.add("rose");
list.add("cxk");
list.add("李雷");
list.add("韩梅梅");
list.add(1, "马冬梅");
System.out.println(list);
list.addFirst("尼古拉斯");
list.addLast("亚洲舞王");
System.out.println(list);
System.out.println("================================================");
System.out.println(list.getFirst());
System.out.println(list.getLast());
System.out.println(list.get(3));
System.out.println("================模拟栈结构==================");
LinkedList<String> list1 = new LinkedList<String>();
list1.push("aa");
list1.push("bb");
System.out.println(list1.pop());
System.out.println(list1.pop());
System.out.println("================模拟对列结构==================");
LinkedList<String> list2 = new LinkedList<String>();
//向对列的尾部添加元素
list2.offer("哈哈");
list2.offer("呵呵");
list2.offer("嘻嘻");
list2.offer("hiahia");
//获取并移除对列的头部的元素
System.out.println(list2.poll());
System.out.println(list2.poll());
System.out.println(list2.poll());
System.out.println(list2.poll());
//获取但不移除对列的头部的元素
//System.out.println(list2.element());
//获取但不移除对列的头部的元素
//System.out.println(list2.peek());
System.out.println(list2);
//LinkedList集合三种遍历方式
}
}
14.6.2 LinkedList实现原理
实现原理 |
---|
14.6.3 堆栈和队列结构
堆栈和队列结构 |
---|
14.7 Vector类
14.7.1 常用方法
与
ArrayList
的方法基本一致
public class VectorDemo {
public static void main(String[] args) {
Vector<String> vector = new Vector<String>();
vector.add("aa");
System.out.println(vector);
/**
* ArrayList、LinkedList、Vector的区别
*
* ArrayList和Vector底层使用数组实现(增删慢、查询快)
* ArrayList是当添加元素的时候,才会扩容数组,默认长度为10
* Vector是当创建对象的是,就创建长度为10的数组
* ArrayList线程不安全,效率高
* Vector是线程安全的,效率低
*
* LinkedList底层使用双向链表实现(增删快、查询慢)
*/
}
}
14.7.2 实现原理
与
ArrayList
的底层一致,使用数组实现
14.7.3 常见面试问题
ArrayList
、LinkedList
、Vector
的区别:
- ArrayList和Vector底层使用数组实现(增删慢、查询快)
- ArrayList是当添加元素的时候,才会扩容数组,默认长度为10, Vector是当创建对象的是,就创建长度为10的数组
- ArrayList线程不安全,效率高 Vector是线程安全的,效率低
- LinkedList底层使用双向链表实现(增删快、查询慢)
14.8 HashSet类
14.8.1 HashSet基本使用
常用方法与Collection接口中定义的方法一致
特点:
- 无序 (插入顺序)
- 无下标
- 不可重复
HashSet<String> set = new HashSet<String>();
set.add("jack");
set.add("rose");
set.add("cxk");
set.add("jack");
System.out.println(set);
14.8.2 HashSet 去重原理
HashSet底层去重:
首先会比较两个对象的hashCode的值,如果hashCode值不一样,则直接认为两个对象是不同的对象,如果HashCode值一样,那么就会比较两个方法的equals方法, 如果equals方法返回false,则表示两个对象是不同的对象,如果equals方法返回true,则表示两个对象是相同的对象,则不会向HashSet中添加
总之:HashSet确定对象是否重复,是先判断hashcode再判断equals,两者都相等则认为是相同对象
HashSet<User> userSet = new HashSet<User>();
User cxk = new User("cxk", "123");
userSet.add(cxk);
userSet.add(new User("jack", "456"));
userSet.add(new User("王校长", "输液..."));
userSet.add(new User("jack", "456")); // 相同对象无法插入
userSet.add(cxk);// 相同对象无法插入
重写
hashCode
和equals
方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((password == null) ? 0 : password.hashCode());
result = prime * result + ((username == null) ? 0 : username.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
//判断两个对象是否是同一个对象
if (this == obj)
return true;
//判断比较的对象是否为null
if (obj == null)
return false;
//getClass() 返回对象的真实(运行)类型
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (password == null) {
if (other.password != null)
return false;
} else if (!password.equals(other.password))
return false;
if (username == null) {
if (other.username != null)
return false;
} else if (!username.equals(other.username))
return false;
return true;
}
14.9 LinkedHashSet类
LinkedHashSet
特点::
- 1、有序
- 2、无下标
- 3、不可重复
与父类的方法一致,去重的原理,也与父类一致
public class LinkedHashSetDemo {
public static void main(String[] args) {
//LinkedHashSet 有序(链表维护顺序) 不能重复
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("jack");
set.add("大娃");
set.add("二娃");
set.add("rose");
set.add("爷爷");
set.add("爷爷");
for (String s : set) {
System.out.println(s);
}
//1、底层实现 (LinkedHashMap)
//2、去重原理 (与hashSet一致)
}
}
14.10 Collections工具类
集合: 工具类(Collections)
- Collections.reverse(List<?> list)
- 将集合中的元素反转
- Collections.shuffle(List<?> list)
- 将集合中的元素随机打乱
- Collections.sort(List<?> list)
- 将集合中的元素排序 (必须要实现Comparable接口)
public class CollectionsDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("jack");
list.add("大娃");
list.add("二娃");
list.add("rose");
list.add("妖怪");
list.add("蛇妖");
list.add("蛇妖");
System.out.println(list);
//按照字典顺序
Collections.sort(list);
System.out.println(list);
//将集合元素进行翻转
Collections.reverse(list);
System.out.println(list);
//将集合中的元素进行随机打乱
Collections.shuffle(list);
System.out.println(list);
//Arrays数组工具类 Collections集合工具类
}
}