java基础(集合)

集合1 集合1.1 概述1.2 Collection接口1.3 迭代器1.4 foreach循环1.5 数据结构1.6 List集合1.7 List实现类1.8 Set集合1.9 Set实现类1.10 Map集合1.11 Map实现类1.12 Map的遍历1.13 集合工具类1.14 案例1 集合1.1 概述集合是JavaAPI中提供的一种容器工具,可以用来存储多个数据。集合和数组之间的区别有:数组的长度是固定的,集合的长度是可变的数组中存储的是同一类型的元素,集合中存储的数据可以是不同类型的
摘要由CSDN通过智能技术生成

1 集合

1.1 概述

集合是JavaAPI中提供的一种容器工具,可以用来存储多个数据。

集合和数组之间的区别有:

  • 数组的长度是固定的,集合的长度是可变的
  • 数组中存储的是同一类型的元素,集合中存储的数据可以是不同类型的
  • 数组中可以存放基本类型数据或者对象,集合中只能存放对象
  • 数组是由JVM中现有的 类型+[] 组合而成的,除了一个length属性,还有从Object中继承过来的方法之外,数组对象就调用不到其他属性和方法了
  • 集合是由JavaAPI中的java.util包里面所提供的接口和实现类组成的,这里面定义并实现了很多方法,可以使用集合对象直接调用这些方法,从而操作集合存放的数据

集合框架中主要有三个要素组成:

  1. 接口

    整个集合框架的上层结构,都是用接口进行组织的。

    接口中定义了集合中必须要有的基本方法。

    通过接口还把集合划分成了几种不同的类型,每一种集合都有自己对应的接口。

  2. 实现类
    对于上层使用接口划分好的集合种类,每种集合的接口都会有对应的实现类。

    每一种接口的实现类很可能有多个,每个的实现方式也会各有不同。

  3. 数据结构

    每个实现类都实现了接口中所定义的最基本的方法,例如对数据的存储、检索、操作等方法。

    但是不同的实现类,它们存储数据的方式不同,也就是使用的数据结构不同。

集合按照其存储结构可以分为两大类:

  • java.util.Collection
  • java.util.Map

其他的集合接口,都是由这俩个接口派生出来的:

在这里插入图片描述

注意1,图中列出的是java集合框架中的主要接口,以及它们之间的继承关系

注意2,接口中定义了该种集合具有的主要方法,以及集合的基本特点

注意3,将来真正要使用的,是这些接口的实现类,每种实现类对接口的实现方式不同,那么其特点也不同

1.2 Collection接口

Collection接口是单列集合类的父接口,这种集合可以将数据一个一个的存放到集合中。它有两个重要的子接口,分别是java.util.Listjava.util.Set

Collection是父接口,其中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合对象。

Collection类型集合必须要有的基本的方法:

//向集合中添加元素	
boolean 	add(E e)
//把一个指定集合中的所有数据,添加到当前集合中    
boolean 	addAll(Collection<? extends E> c)
//清空集合中所有的元素。    
void 		clear()
//判断当前集合中是否包含给定的对象。
boolean 	contains(Object o)
//判断当前集合中是否包含给定的集合的所有元素。    
boolean 	containsAll(Collection<?> c)
//判断当前集合是否为空。
boolean 	isEmpty()
//返回遍历这个集合的迭代器对象    
Iterator<E> iterator()
//把给定的对象,在当前集合中删除。
boolean 	remove(Object o)
//把给定的集合中的所有元素,在当前集合中删除。    
boolean 	removeAll(Collection<?> c)
//判断俩个集合中是否有相同的元素,如果有当前集合只保留相同元素,如果没有当前集合元素清空    
boolean 	retainAll(Collection<?> c)
//返回集合中元素的个数。    
int 		size()
//把集合中的元素,存储到数组中。    
Object[] 	toArray()
//把集合中的元素,存储到数组中,并指定数组的类型  
<T> T[] 	toArray(T[] a)

一些方法的使用样例:

public static void main(String[] args) {
   

    //ArrayList类是Collection集合的一个实现类
    Collection c1 = new ArrayList();
    c1.add("hello1");
    c1.add("hello2");
    c1.add("hello3");


    //默认调用集合的toString方法,输出集合中内容
    System.out.println("操作之前集合中元素:"+c1);
    System.out.println("集合中的元素个数:"+c1.size());

    System.out.println("集合中是否包含hello1:"+c1.contains("hello1"));

    System.out.println("删除hello1:"+c1.remove("hello1"));
    System.out.println("操作之后集合中元素:"+c1);

    Object[] objects = c1.toArray();

    for (int i = 0; i < objects.length; i++) {
   
        System.out.println(objects[i]);
    }

    c1.clear();

    System.out.println("集合中内容为:"+c1);

    System.out.println(c1.isEmpty());

}

1.3 迭代器

为了能够方便的遍历集合中的每一个元素,API中提供了一个迭代器接口:java.util.Iterator

该接口可以很方便的迭代出集合中的元素。

java.lang.Iterable接口中,定义了获取迭代器的方法:

public interface Iterable {
   
    Iterator iterator();
}

java.util.Collection接口继承了java.lang.Iterable接口

public interface Collection extends Iterable {
   
    //...
}

所以,Collection接口及其子接口中,都有一个获取迭代器对象的方法:Iterator iterator();

java.util.Iterator接口中,主要定义俩个方法:

public interface Iterator {
   
    boolean hasNext();//返回当前迭代器中是否还有下一个对象
    Object next();//获取迭代器中的下一个对象
}

例如,

public static void main(String[] args) {
   

    Collection c1 = new ArrayList();
    c1.add("hello1");
    c1.add("hello2");
    c1.add("hello3");

	//获取c1集合的迭代器对象
    Iterator iterator = c1.iterator();
    
    //判断迭代器中,是否还有下一个元素
    while(iterator.hasNext()){
   
        //如果有的话,就取出来
        Object obj = iterator.next();
        System.out.println(obj);
    }


}

注意,这种迭代器方式获取集合中的每一个元素,是Collection集合及其子类型集合通用的方式

1.4 foreach循环

除了使用迭代器遍历集合之外,使用JDK1.5及以上提供的增强for循环,也可以遍历集合。

foreach循环的格式:

for(变量类型 变量名 : 集合){
   
    //操作变量
}

相当于,每次循环,使用指定变量,去指向集合中的一个对象,然后在循环体中对该变量进行操作

例如,

public static void main(String[] args) {
   

    Collection<String> c1 = new ArrayList<>();
    c1.add("hello1");
    c1.add("hello2");
    c1.add("hello3");

	for(Object o:c1){
   
        System.out.println(o);
    }


}

可以看出,使用foreach循环对集合进行遍历,会更加简单一些

同时,使用foreach循环也可以遍历数组

public static void main(String[] args) {
   

    int[] arr = {
   1,3,5,7,9};
	
    //每次循环,使用变量i接收数组中的一个数据
	for(int i : arr){
   
        System.out.println(i);
    }

}

注意,Collection类型及其子类型的集合,还有数组,都可以使用foreach循环进行遍历其中的元素数据

1.5 数据结构

集合接口都会有不同的实现类,每种实现类的底层,采用了不同的数据结构对数据元素进行存储

数据存储的常用结构有:

  • 队列
  • 数组
  • 链表
  • 红黑树
  • 哈希表

数据结构:栈

栈(stack),又称堆栈,仅允许在栈的一端进行插入和删除操作,并且不允许在其他任何位置进行操作。

其特点是:先进后出,最先存进去的元素,最后才能取出来。

例如,薯片存在薯片桶中,我们当前只能取出最上面的一个薯片,而最早存放到薯片桶的薯片,反而是我们最后吃到的一片。

栈的入口、出口的都是栈的顶端位置:

在这里插入图片描述

注意1,入栈也称为压栈,把数据存入到栈的顶端位置

注意2,出栈也称为弹栈,把栈顶位置的数据取出

思考,JVM中的栈区中,为什么把main方法标注在最低端位置?

数据结构:队列

队列(queue),仅允许在队列的一端进行插入,而在队列的另一端进行删除。

其特点是:先进先出,最先存进去的元素,可以最先取出来。

例如,火车穿过山洞的时候,第一节车厢先进去山洞的一端,并且这节车厢优先从山洞的另一端出来,后面的车厢依次从一端进入并另一端出来。

队列的入口、出口分别在队列的俩端:

数据结构:数组

数组(array),内存中一块连续的空间,元素数据在其中按照下标索引依次存储,比较常用的数据结构。

其特点是:通过下标索引,可以快速访问指定位置的元素,但是在数组中间位置添加数据或者删除数据会比较慢,因为数组中间位置的添加和删除元素,为了元素数据能紧凑的排列在一起,那么就会引起其后面的元素移动位置。

所以,数组查询元素较快,中间位置的插入、删除元素较慢。

可以看出,数组中间添加数据后,之后的数据都要依次移动位置。同理,中间位置删除的时候也是这样

数据结构:链表

链表(linked list),是有一个一个node节点组成,每个node节点中存储了一个数据,以及一个指向下一个node节点对象的引用(单向链表),如果是双向链表的话,还会存储另一个引用,指向了上一个node节点对象。

其特点是:

  • 查找元素慢,因为需要通过连接的节点,依次向后查找指定元素(没有直接的下标索引)
  • 新增和删除元素较快,例如删除,只需要让当前node节点中的引用指向另一个节点对象即可,原来的指向的node节点就相当于删除了。

可以看出,只需要将数据2节点中的引用,指向数据4的节点对象即可

head表示链表的头部,tail表示链表的尾部

思考,是否能根据单向链表的特点,想象出双向链表的特点?

数据结构:红黑树

二叉树(Binary tree)是树形结构的一个重要类型。二叉树特点是每个结点最多只能有两棵子树,且有左右之分。

二叉树顶上的叫根结点,两边被称作“左子树”和“右子树”。

二叉树中有一种叫做红黑树(Red/Black Tree),它最早被称为平衡二叉B树(symmetric binary B-trees),后来被称为红黑树。

红黑树是一种特殊化的平衡二叉树,它可以在进行插入和删除的时候,如果左右子数的高度相差较大,那么就通过特定操作(左旋、右旋)保持二叉查找树的平衡(动态平衡),从而获得较高的查找性能。

红黑树的每一个节点的左子树的所有数据都比自己小,而右子树的所有数据都比自己大,并且左右子树的高度近似

红黑树的约束:

  1. 根节点必须是黑色
  2. 其他节点可以是红色的或者黑色
  3. 叶子节点(特指null节点)是黑色的
  4. 每个红色节点的子节点都是黑色的
  5. 任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同

注意,红黑树的指定颜色的目的,是利用颜色值作为二叉树的平衡对称性的检查

数据结构:哈希表

java中的哈希表(hash),在JDK1.8之前是采用数组+链表进行实现,根据数据的哈希值,把数据存在数组中,但是当前哈希值冲突的时候,再使用链表进行存储,那么在数组中,同一hash值的数据都存在一个链表里。

注意,之前学习过Object中hashCode方法的作用,hash值的特点以及和对象之间的关系

例如,

例如,如果数据的哈希值相同,在数组使用使用链表存储哈希值相同的几个数据

可以看出,当链表中元素过多,即hash值相等的元素较多时,查找的效率会变低

JDK1.8中,哈希表存储采用数组+链表+红黑树进行实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样可以大大提高查找的性能。

例如,

思考,java的集合框架中,三个重要组成部分是什么?

接口、实现类、数据结构

1.6 List集合

java.util.List 接口继承了Collection 接口,是常用的一种集合类型。

List集合具有Collection集合的特点之外,还具有自己的一些特点:

  • List是一种有序的集合

    例如,向集合中存储的元素顺序是8、2、5。那么集合中就是按照这个顺序进行存储的

  • List是一种带索引的集合

    可以通过元素的下标索引,精确查找对应的元素数据

  • List是一种可以存放重复数据的集合

    可以把相同的数据,在List集合中多次保存

List接口中常用方法:

//返回集合中指定位置的元素。
E		get(int index);
//用指定元素替换集合中指定位置的元素,并返回被替代的旧元素。
E		set(int index, E element);
//将指定的元素,添加到该集合中的指定位置上。
void	add(int index, E element);
//从指定位置开始,把另一个集合的所有元素添加进来
boolean addAll(int index, Collection<? extends E> c);
//移除列表中指定位置的元素, 并返回被移除的元素。
E		remove(int index);
//查收指定元素在集合中的所有,从前往后查到的第一个元素(List集合可以重复存放数据)
int		indexOf(Object o);
//查收指定元素在集合中的所有,从后往前查到的第一个元素(List集合可以重复存放数据)
int		lastIndexOf(Object o);
//根据指定开始和结束位置,截取出集合中的一部分数据
List<E> subList(int fromIndex, int toIndex);

注意,除了这些方法之外,还有从父接口Collection中继承过来的方法

List集合的方法使用:

public static void main(String[] args) {
   

    // 创建List集合对象
    List list = new ArrayList();
    // 往 尾部添加 指定元素
    list.add("hello1");
    list.add("hello2");
    list.add("hello3");
    System.out.println(list);
    // add(int index,String s) 往指定位置添加
    list.add(1, "world");
    System.out.println(list);

    // 删除索引位置为2的元素
    System.out.println("删除索引位置为2的元素");
    System.out.println(list.remove(2));
    System.out.println(list);

    // 修改指定位置元素
    list.set(0, "briup");
    System.out.println(list);

    //遍历集合
    for (int i = 0; i < list.size(); i++) {
   
        System.out.println(list.get(i));
    }

    System.out.println("-----------------");
    //使用foreach遍历
    for(Object obj : list){
   
        System.out.println(obj);
    }

    System.out.println("-----------------");
    //使用迭代器进行遍历集合
    Iterator it = list.iterator();
    while(it.hasNext())
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值