概述
需要学会什么
- 集合概述体系、常用API
- 集合遍历、存储对象
- 常用数据结构
- List系列集合
- 泛型深入
数组的特点
- 数组定义完成并启动后,类型确定、长度固定
- 适合元素的个数和类型确定的业务场景,不适合做需要增删数据操作
集合的特点
- 集合的大小不固定,启动后可以动态变化,类型也可以选择不固定。集合更像气球
- 集合非常适合做元素的增删操作
集合的代表
- Collection接口
Collection集合2大常用的集合体系
- List系列集合:添加的元素是有序、可重复、有索引
- Set系列集合:添加的元素是无序、不重复、无索引
注意:
- 集合支持泛型
- 集合和泛型不支持基本类型,只支持引用数据类型
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
public class test {
public static void main(String[] args) {
// 有序 可重复 有索引
Collection list=new ArrayList();
list.add("1");
list.add("2");
list.add("3");
System.out.println(list);
//无序 不重复 不索引
Collection L=new HashSet();
L.add("a");
L.add("b");
L.add("c");
System.out.println(L);
// 集合和泛型不支持基本数据类型,只能支持引用数据类型
Collection<String> Li=new ArrayList<>();
Li.add("张三");
Li.add("ad");
System.out.println(Li);
Collection<Integer> Ls=new ArrayList<>();
Ls.add(123);
Ls.add(456);
System.out.println(Ls);
}
}
输出
[1, 2, 3]
[a, b, c]
[张三, ad]
[123, 456]
Collection集合的常用API - public boolean add(E e): 把给定的对象添加到当前集合中 。 - public void clear() :清空集合中所有的元素。 - public boolean remove(E e): 把给定的对象在当前集合中删除。 - public boolean contains(Object obj): 判断当前集合中是否包含给定的对象。 - public boolean isEmpty(): 判断当前集合是否为空。 - public int size(): 返回集合中元素的个数。 - public Object[] toArray(): 把集合中的元素,存储到数组中。
class test2 {
public static void main(String[] args) {
Collection <String > a=new ArrayList<>();
a.add("zhangsan");
System.out.println(a.add("李4"));
a.add("123");
a.add("123");
//成功返回ture
System.out.println(a);
//清空集合元素
//a.clear();
System.out.println(a);
//判断集合是否为空
System.out.println(a.isEmpty()); //是为ture
// 获取集合的大小
System.out.println(a.size());
//判断集合中是否有包含某个元素
System.out.println(a.contains("zhangsan")); //ture
//删除某个元素:如果有多个重复元素默认删除前面的第一个
System.out.println(a.remove("123"));
//把集合转成数组 [zhangsan, 李4, 123, 123]
Object arr []=a.toArray();
System.out.println("数组"+ Arrays.toString(arr));
//把一个集合的元素全部倒入另一个人集合中
Collection<String> c1 = new ArrayList<>();
c1.add("java1");
c1.add("java2");
Collection<String> c2 = new ArrayList<>();
c2.add("赵敏");
c2.add("殷素素");
// addAll把c2集合的元素全部倒入到c1中去。
c1.addAll(c2);
System.out.println(c1);
System.out.println(c2);
Collection集合的遍历方式
什么是遍历? 为什么开发中要遍历? 遍历就是一个一个的把容器中的元素访问一遍。 开发中经常要统计元素的总和,找最值,找出某个数据然后干掉等等业务都需要遍历。
Collection集合的遍历方式是全部集合都可以直接使用的,所以我们学习它。 Collection集合的遍历方式有三种: (1)迭代器。 (2)foreach(增强for循环)。 (3)JDK 1.8开始之后的新技术Lambda表达式(了解)
迭代器遍历集合。 -- 方法: public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的 boolean hasNext():判断是否有下一个元素,有返回true ,反之。 E next():获取下一个元素值! --流程: 1.先获取当前集合的迭代器 Iterator<String> it = lists.iterator(); 2.定义一个while循环,问一次取一次。 通过it.hasNext()询问是否有下一个元素,有就通过 it.next()取出下一个元素。
如果越界会产生会出现NoSuchElementException异常
法1
public class test1 {
public static void main(String[] args) {
ArrayList<String> a=new ArrayList<>();
a.add("我");
a.add("是");
a.add("笨");
a.add("蛋");
System.out.println(a);
Iterator<String> it =a.iterator();
String ele= it.next();
System.out.println(ele);
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
}
}
结果
[我, 是, 笨, 蛋]
我
是
笨
蛋
迭代器法2(重要)
public class test1 {
public static void main(String[] args) {
ArrayList<String> a=new ArrayList<>();
a.add("我");
a.add("是");
a.add("笨");
a.add("蛋");
System.out.println(a);
Iterator<String> it =a.iterator();
while(it.hasNext()){
String ele=it.next();
System.out.println(ele);
}
}
}
结果
[我, 是, 笨, 蛋]
我
是
笨
蛋
增强for循环
foreach(增强for循环)遍历集合。 foreach是一种遍历形式,可以遍历集合或者数组。 foreach遍历集合实际上是迭代器遍历集合的简化写法。 foreach遍历的关键是记住格式: for(被遍历集合或者数组中元素的类型 变量名称 : 被遍历集合或者数组){ }
public class test2 {
public static void main(String[] args) {
Collection<String> a=new ArrayList<>();
a.add("我");
a.add("是");
a.add("笨");
a.add("蛋");
System.out.println(a);
for(String els :a){//这是集合
System.out.println(els);
}
System.out.println("---------------------");
double [] b={66,99,77};//遍历数组
for (double ele : b) {
System.out.println(ele);
}
}
}
结果是
[我, 是, 笨, 蛋]
我
是
笨
蛋
---------------------
66.0
99.0
77.0
案例
public class test {
public static void main(String[] args) {
Collection<movies> a=new ArrayList<>();
a.add(new movies("好看的电影",9.0,"1"));
a.add(new movies("不好看",0.0,"2"));
a.add(new movies("一般的",5.5,"3"));
System.out.println(a);
for (movies s : a) {//不能用索引,所以只能用集合的强循环
System.out.println("片名: "+s.getNames());
System.out.println("得分: "+s.getScores());
System.out.println("演员: "+s.getActor());
}
}
}
public class movies {
private String names;
private double scores;
private String actors;
public movies(String names, double scores, String actor) {
this.names = names;
this.scores = scores;
this.actors = actor;
}
public String getNames() {
return names;
}
public void setNames(String names) {
this.names = names;
}
public double getScores() {
return scores;
}
public void setScores(double scores) {
this.scores = scores;
}
public String getActor() {
return actors;
}
public void setActor(String actor) {
this.actors = actor;
}
结果
片名: 好看的电影
得分: 9.0
演员: 1
片名: 不好看
得分: 0.0
演员: 2
片名: 一般的
得分: 5.5
演员: 3
常见数据结构
栈
特点:后进先出,先进后出
队列
特点:先进先出,后进后出
数组
- 查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同
- 删除效率低:要将原始数据删除,同时后面每个数据前移
- 添加效率极低:添加位置后的每个数据后移,再添加元素
链表
- 链表中的元素是在内存中不连续存储的,每个元素节点包含数据值和下一个元素的地址
- 链表查询慢。无论查询哪个数据都要从头开始找
- 链表增删相对快
二叉树
- 只能有一个根节点,每个节点最多支持2个直接子节点
- 节点的度: 节点拥有的子树的个数,二叉树的度不大于2 叶子节点 度为0的节点,也称之为终端结点。
- 高度:叶子结点的高度为1,叶子结点的父节点高度为2,以此类推,根节点的高度最高。
- 兄弟节点 :拥有共同父节点的节点互称为兄弟节点
普通二叉树
- 每一个节点上最多有两个子节点
- 左子树上所有节点的值都小于根节点的值
- 右子树上所有节点的值都大于根节点的值
- 目的:提高检数据的性能
红黑树
- 红黑树是一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构
- 每一个节点可以是红或者黑;红黑树不是通过高度平衡的,它的平衡是通过“红黑规则”进行实现的。
红黑树规则
- 每一个节点或是红色的,或者是黑色的,根节点必须是黑色
- 如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)
- 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
规则如下
每一个节点或是红色的,或者是黑色的,根节点必须是黑色
如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的
如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)
对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
红黑树增删改查的性能都很好
List系列集合特点
ArrayList、LinekdList :有序,可重复,有索引
有序:存储和取出的元素顺序一致
有索引:可以通过索引操作元素
可重复:存储的元素可以重复
public class test {
public static void main(String[] args) {
// 1.创建一个ArrayList集合对象:
// List:有序,可重复,有索引的。
ArrayList<String> a = new ArrayList<>(); // 一行经典代码!
a.add("Java");
a.add("Java");
a.add("HTML");
a.add("HTML");
a.add("MySQL");
a.add("MySQL");
// 在某个索引位置插入元素。
a.add(2, "牛pi");
System.out.println(a);
//根据索引删除元素,返回被删除元素
System.out.println(a.remove(1));
System.out.println(a);
// .根据索引获取元素:public E get(int index):返回集合中指定位置的元素。
System.out.println(a.get(1));
// 修改索引位置处的元素: public E set(int index, E element)
System.out.println(a.set(1, "鸡"));
System.out.println(a);
}
}
List系列集合的遍历方式有:4种
第一种
for循环
for (int i = 0; i < lists.size(); i++) {
String ele = lists.get(i);
System.out.println(ele);
}
第二种
迭代器
Iterator<String> it = lists.iterator();
while (it.hasNext()){
String ele = it.next();
System.out.println(ele);
}
第三种
foreach
System.out.println("-----------------------");
for (String ele : lists) {
System.out.println(ele);
}
第四
Lambda表达式
lists.forEach(s -> {
System.out.println(s);
});
ArrayList底层原理
ArrayList底层是基于数组实现的:根据索引定位元素快,增删需要做元素的移位操作
第一次创建集合并添加第一个元素的时候,在底层创建一个默认长度为10的数组
List<String> list = new ArrayList<>();
list.add("a");
LinkedList的特点
底层数据结构是双链表,查询慢,首尾操作的速度是极快的,所以多了很多首尾操作的特有API
LinkedList也是List的实现类:底层是基于双链表的,增删比较快,查询慢!!
LinkedList是支持双链表,定位前后的元素是非常快的,增删首尾的元素也是最快的 所以LinkedList除了拥有List集合的全部功能还多了很多操作首尾元素的特殊功能:
- public void addFirst(E e):将指定元素插入此列表的开头。
- public void addLast(E e):将指定元素添加到此列表的结尾
- public E getFirst():返回此列表的第一个元素。
- public E getLast():返回此列表的最后一个元素。
- public E removeFirst():移除并返回此列表的第一个元素。
- public E removeLast():移除并返回此列表的最后一个元素。
- public E pop():从此列表所表示的堆栈处弹出一个元素。
- public void push(E e):将元素推入此列表所表示的堆栈。
import java.util.LinkedList;
public class test3 {
public static void main(String[] args) {
LinkedList<String > a=new LinkedList<>();//类比入栈
a.addFirst("第一个子弹");
a.addFirst("第二个");
a.addFirst("第三个");
a.addFirst("第四个");
System.out.println(a);
System.out.println(a.pop());
System.out.println(a.pop());
System.out.println(a.pop());
System.out.println(a);//出栈 弹栈 pop
LinkedList<String> q =new LinkedList<>();//入队出队
q.addLast("1");
q.addLast("2");
q.addLast("3");
System.out.println(q);
}
}
集合的一些并发修改异常问题
案例 集合的删除问题
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("2");
list.add("4");
list.add("5");
list.add("6");
System.out.println(list);
方法1 用迭代器
Iterator<String> it = list.iterator();
while (it.hasNext()){
String ele = it.next();
if("2".equals(ele)){
// 删除Java
// list.remove(ele); // 集合删除会出毛病
it.remove(); // 删除迭代器所在位置的元素值(没毛病)得用迭代器的
}
}
方法2 用for 循环
for (int i = list.size() - 1; i >= 0 ; i--) {
String ele = list.get(i);
if("2".equals(ele)){
list.remove(ele);
}
}
System.out.println(list);
}
}
或者
for (int i =0; i < List.size() ; i++) {
String ele = list.get(i);
if("2".equals(ele)){
list.remove(ele);
i--;
}
}
System.out.println(list);
}
}
迭代器遍历集合但是用迭代器自己的删除方法操作可以解决。
使用for循环遍历并删除元素不会存在这个问题。
目标:泛型的概述。 什么是泛型? 泛型就是一个标签:<数据类型> 泛型可以在编译阶段约束只能操作某种数据类型。 泛型可以在编译阶段约束只能操作某种数据类型。 泛型只能支持引用数据类型。
泛型类
import java.util.ArrayList;
public class MyArrayList<E> { //泛型类
private ArrayList lists = new ArrayList();
public void add(E e){
lists.add(e);
}
public void remove(E e){
lists.remove(e);
}
@Override
public String toString() {
return lists.toString();
}
}
public class Test {
public static void main(String[] args) {
// 需求:模拟ArrayList定义一个MyArrayList ,关注泛型设计
MyArrayList<String> list = new MyArrayList<>();
list.add("Java");
list.add("Java");
list.add("MySQL");
list.remove("MySQL");
System.out.println(list);
MyArrayList<Integer> list2 = new MyArrayList<>();
list2.add(23);
list2.add(24);
list2.add(25);
list2.remove(25);
System.out.println(list2);
}
}
泛型方法
定义方法时同时定义了泛型的方法就是泛型方法
泛型方法的格式:修饰符 <泛型变量> 方法返回值 方法名称(形参列表){}
注意:方法定义了是什么泛型变量,后面就只能用什么泛型变量。
public <T> void show(T t) { }
作用:方法中可以使用泛型接收一切实际类型的参数,方法更具备通用性
public static <T> T[] getArr(T[] arr){
return arr;
}
public static <T> void printArray(T[] arr){
if(arr != null){
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < arr.length; i++) {
sb.append(arr[i]).append(i == arr.length - 1 ? "" : ", ");
}
sb.append("]");
System.out.println(sb);
}else {
System.out.println(arr);
}
}
}
泛型方法核心思想
把出现泛型的地方全部转成真实数据类型
泛型接口的概述
使用了泛型定义的接口就是泛型接口。 泛型接口的格式:修饰符 interface 接口名称<泛型变量>{}
泛型的通配符
? 可以在“使用泛型”的时候代表一切类型
E T K V 是在定义泛型的时候使用的
泛型的上下限
? extends Car: ?必须是Car或者其子类 泛型上限
? super Car : ?必须是Car或者其父类 泛型下限
运用案例
public class GenericDemo {
public static void main(String[] args) {
ArrayList<BMW> bmws = new ArrayList<>();
bms.add(new BM());
bms.add(new BM());
bms.add(new BM());
go(bmws);
ArrayList<BENZ> benzs = new ArrayList<>();
bzs.add(new BZ());
bzs.add(new BZ());
bzs.add(new BZ());
go(benzs);
ArrayList<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
dogs.add(new Dog());
dogs.add(new Dog());
// go(dogs);
}
/**
所有车比赛
*/
public static void go(ArrayList<? extends Car> cars){ //进行上下限的限制,防止
}
}
class Dog{
}
class BZ extends Car{
}
class BM extends Car{
}
// 父类
class Car{
}
最后
以上就是风中帅哥为你收集整理的集合 Collection、数据结构、List、泛型深入等知识点的全部内容,希望文章能够帮你解决集合 Collection、数据结构、List、泛型深入等知识点所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复