Java入门-java的集合框架

news2024/11/15 16:02:08

集合概念

集合,有时也称作容器(Container), 是对象的持有者,它们可以有助于高效访问的方式存储的组织对象。以生活中的案例为例: 集合就像装衣服的柜子,衣服就是集合中的元素。

img

集合框架图

image-20240527172334115

Collection中每次操作的都是一个对象,如果要操作一对对象就必须使用Map,Map中所有的对象都按照key->value形式保存,也称二元偶对象。Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法。Collections 类是 Java 提供的一个操作 Set、List 和 Map 等集合的工具类。

泛型

泛型概念

把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型。

泛型一般表示为<E>

例如:

public class ArrayList<E> implements List<E>{
    
}

这个ArrayList类中用到的类,用E替代(泛型), 当创建对象时才明确它的类型。

new ArrayList<String>(); //创建对象时泛型明确为String类型

为什么使用泛型?

  • 使代码更加简洁

  • 使程序更加健壮

  • 提高可读性和稳定性

程序案例:

List<User> users = new ArrayList<>();
User user = new User();
users.add(user); 

如程序演示:使用泛型定义了对象使用类型为Dog类型,如果使用其它类型编译器检查则会报错,早检查出错增强程序的健壮性。

泛型的擦除

java的一个特性,在运行时,java不会保留泛型。

Java 泛型的参数只可以代表类,不能代表个别对象。由于Java泛型的类型参数之实际类型在编译时会被消除,所以无法在运行时得知其类型参数的类型。Java 编译器在编译泛型时会自动加入类型转换的编码,故运行速度不会因为使用泛型而加快。

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。

通配符泛型

无边界通配符: 例如List<?> , ? 表示不确定的java类型。

固定上边界通配符: 例如List<? extends Car> ,表示指定类的子类,Car即为上边界。

固定下边界通配符: 例如List<? super Car>,表示Car的父类,Car即为下边界。

Collection接口

The root interface in the collection hierarchy。

集合层次结构的根接口。定义了集合的常用api。

image-20240527172736069

List接口

List接口是Collection接口的子接口。有序的集合,存储元素和取出元素的顺序是一致的(存储abc则取出abc)有索引,包含了一些带索引的方法允许存储重复的元素。

ArrayList

ArrayList类特性

底层由动态数组构成,即数组的长度可变。

ArrayList的类层次结构

image-20240526175020435

image-20240526175048180

image-20240526175107499

ArrayList的属性

数组的初始长度为10

private static final int DEFAULT_CAPACITY = 10;

private static final Object[] EMPTY_ELEMENTDATA ={};

 //第一次添加元素时知道该 elementData 从空的构造函数还是有参构造函数被初始化的。以便确认如何扩容。

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA ={};

transient Object[] elementData;// non-private to simplify nested class access

private int size;

//数组最大的分配容量

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
构造方法

无参构造方法

当使用默认构造方法时,对象数组指向DEFAULTCAPACITY_EMPTY_ELEMENTDATA容量为0,当第一次添加数据时,将数组的长度扩展为默认大小DEFAULT_CAPACITY。

源码分析:

public ArrayList() {
   this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

有参构造方法 初始化数组的长度

源码分析:

public ArrayList(int initialCapacity) {

   if(initialCapacity > 0) {
     this.elementData = new Object[initialCapacity];
  }else if (initialCapacity == 0) {
    this.elementData = EMPTY_ELEMENTDATA;
  } else {
  	throw new  IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
  }
}
添加元素
add(E e):添加 元素

List\<Integer> list = new ArrayList<>();

list.add(1);

源码分析:

public boolean  add(E e) {

   ensureCapacityInternal(size + 1);  // 确认容量是否足够

   elementData[size++] = e;

   return true ;

 }

确认最小空间

private void  ensureCapacityInternal( int  minCapacity) {

  ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

初始化数组空间大小

private static int  calculateCapacity(Object[] elementData, int minCapacity){

//如果是空数组,则将数组长度变为DEFAULT_CAPACITY=10;
  if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
       return Math.max(DEFAULT_CAPACITY\*, minCapacity);
 }
  return minCapacity;
}

实现数组的扩容处理

private void ensureExplicitCapacity(int minCapacity) {

  //如果当集合容量+1 > 数组的长度,那么数组要进行扩容

 if (minCapacity - elementData.length > 0) 
      grow(minCapacity);
}

private void grow(int minCapacity) {

   int oldCapacity = elementData.length;
   int newCapacity = oldCapacity + (oldCapacity >> 1); //扩容1.5倍
   if (newCapacity - minCapacity < 0)    newCapacity = minCapacity;
   if (newCapacity - *MAX_ARRAY_SIZE\* > 0) //超过了数组的最大指
    newCapacity = *hugeCapacity*(minCapacity);
  elementData = Arrays.*copyOf*(elementData, newCapacity); //数组扩容
 }
删除元素remove(int index),根据位置删除:

img

list.remove(1); //删除元素-根据位置删除 

源码分析:

public E remove(int index) {
  ......
  E oldValue = elementData(index); //删除之前获取旧数据
  int numMoved = size - index - 1; //要移动的数组元素数量
  if (numMoved > 0)
  System.arraycopy(elementData, index+1, elementData, index,
  numMoved);
  elementData[--size] = null; //将最后一个元素置为null,数组容量-1
  return oldValue;
}
删除元素:根据对象内容删除

删除的对象需要实现equals()方法

boolean remove(Object o) //根据对象删除

List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
list.remove("banana");

源码分析:

我们发现删除时需要调用元素的equals()方法。

public boolean remove(Object o) {
 if (o == null) {
   for (int index = 0; index < size; index++)
    if (elementData[index] == null) {
       fastRemove(index);
       return true;
     }
    } else { 
    for (int index = 0; index < size; index++)
      if (o.equals(elementData[index])) {//使用对象的equals方法比较
      fastRemove(index);
       return true;
      }
    }
  return false;
}

集合中的类型是String,则使用String中的equals()方法,如果为自定义类型,需要重写对象的equals()方法。

/**
 * String类中重写了equals()方法
 */
public boolean equals(Object anObject) {
  if (this == anObject) {
    return true;
  }

  if (anObject instanceof String) {
   String anotherString = (String)anObject;
   int n = value.length;
   if (n == anotherString.value.length) {
     char v1[] = value;
     char v2[] = anotherString.value;
     int i = 0;
     while (n-- != 0) {
      if (v1[i] != v2[i])
       return false;
     i++;
     }
     return true;
      }
    }
   return false;
 }

删除元素源码分析:

private void fastRemove(int index) {

 int numMoved = size - index - 1;
 if (numMoved > 0)
 System.arraycopy(elementData, index+1, elementData, index,numMoved);
 elementData[--size] = null; // clear to let GC do its work
}
修改元素

E set(int index, E e) 修改元素\

list.set(1, "orange");

源码分析:

public E set(int index, E element) {
  E oldValue = elementData(index);
  elementData[index] = element;
  return oldValue;
}
查询元素

E get(int index) 查询元素

list.get(3);

源码分析:

public E get(int index) {
  rangeCheck(index);
  return elementData(index);
} 

LinkedList

什么是链表?

逻辑上连续,空间上不联系,如下图车厢和前后两个车厢相连(双向链表)。

img

如何定义链表(双向链表)
定义节点
private static class Node<E> {

 E item;
 Node<E> next; //连接下一个节点的引用
 Node<E> prev; //连接上一个节点的引用
 Node(Node<E> prev, E element, Node<E> next) {
 this.item = element;
 this.next = next;
 this.prev = prev;
  }
}
2头节点即链表的第一个节点。
transient Node<E> first;
尾节点即链表的最后一个节点
 transient Node<E> last;
设计双向链表(LinkedList的实现)

boolean add(E e) //添加节点

源码分析:

public boolean add(E e) {
  linkLast(e);
  return true;
}

void linkLast(E e) {
   final Node<E> l = last; //记录尾节点
   final Node<E> newNode = new Node<>(l, e, null);
   last = newNode;
   if (l == null) //链表为空,新节点即为第一个节点
	  first = newNode; //头节点指向新节点
   else
     l.next = newNode; //链表不为空,则尾节点连接新节点
   size++;
   :
}

boolean remove(Object o) 删除节点

源码分析:

public boolean remove(Object o) {
    if (o == null) {
      for (Node<E> x = first; x != null; x = x.next) {
       if (x.item == null) {
         unlink(x);
          return true;
        }
      }
    } else {
      for (Node<E> x = first; x != null; x = x.next) {
        if (o.equals(x.item)) {
          unlink(x);
          return true;
       }
     }
    }
   return false;
}
E unlink(Node<E> x) { //x为要删除的节点对象

final E element = x.item;
final Node<E> next = x.next; 
final Node<E> prev = x.prev;

if (prev == null) { //删除头节点
   first = next;
} else {

prev.next = next;//删除节点的前一个节点连接后一个节点
 x.prev = null;
}
if (next == null) {//删除尾节点

  last = prev;

} else {
  next.prev = prev;//删除节点的后一个节点连接前一个节点
  x.next = null;
}
x.item = null;
size--;
return element;
}

E set(int index, E element) 修改节点信息

源码分析:

public E set(int index, E element){
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}

public E get(int index) 查询某个节点信息

源码分析:

public E get(int index) {
   return node(index).item;
}

Node<E> node(int index) {
if (index < (size >> 1)) {
  Node<E> x = first;
  for (int i = 0; i < index; i++) x = x.next;
  return x;
} else {
  Node<E> x = last;
  for (int i = size - 1; i > index; i--) x = x.prev;
  return x;
  }
}

Vector类

Vector 类实现了一个动态数组。。

Vector的类的层次结构

public class Vector<E>
 extends AbstractList<E>
 implements List<E>, RandomAccess, Cloneable, java.io.Serializable

Vector的api

public synchronized boolean add(E e):添加
public synchronized boolean add(E e) {
  ensureCapacityHelper(elementCount + 1);
  elementData[elementCount++] = e;
  return true;
}
public synchronized E remove(int index): 删除
public synchronized E set(int index, E element):修改
public synchronized E get(int index):查询
程序案例:
Vector<String> v = new Vector<>();		
v.add("apple");
v.add("orange");
v.add("banana"); 
v.remove(1);	
v.set(0, "strawberry");		
String f = v.get(1);		
System.*out\*.println(f);
System.*out\*.println(v);

程序运行结果:

banana
[strawberry, banana]

Iterator接口实现元素遍历

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

程序案例:

List<String> l = new ArrayList();
l.add("apple");
l.add("orange");
l.add("banana");
for (Iterator<String> iter = l.iterator(); iter.hasNext();) {
   String str = (String) iter.next();
   System.*out\*.println(str);
}

Stack类

限定仅在表尾进行插入或删除操作的线性表,表尾—栈顶,表头—栈底,不含元素的空表称空栈。

img\

类的结构

image-20240527174910576

Stack常用API

image-20240527175001995

程序案例:

Stack<Integer> stack = new Stack<>();
stack.push(6);
stack.push(2);
stack.push(5);
stack.push(1);

Queue接口

队列(简称作队)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作。队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头。队列的插入操作通常称作入队列,队列的删除操作通常称作出队列。

img

接口结构

image-20240527175136505

Queue常用API

image-20240527175204627

Set接口

set接口是继承自Collection的子接口。

Set接口特性

特点是元素不重复,存储无序。在set接口的实现类中添加重复元素是不会成功的,判断两个元素是否重复根据元素类重写的hashCode()和equals()方法。

Set接口的实现类 HashSet

image-20240527175308483

常用api:

boolean add(E e)boolean remove(Object o)/*底层使用map,删除key*/
  public boolean remove(Object o) {
   return map.remove(o)==*PRESENT\*;
}

其它Set接口的实现类

TreeSet<E>

LinkedHashSet<E>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1706078.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python编程】JetBrains PyCharm IDE专业版 学生优惠过期怎么办?【妥协的解决方法】

写在前面 笔者临近硕士毕业&#xff0c;用了7年左右的JB学生包终于过期了&#xff08;依依不舍&#xff09;。。。之前用得顺手的PyCharm&#xff0c;WebStorm&#xff0c;CLion&#xff08;专业版&#xff09;等等IDE都暂时告别了。笔者无意以个人身份购买许可证&#xff0c;…

android studio 导入github里的项目后提示:Add Configuration

原文链接&#xff1a;https://blog.csdn.net/weixin_45677723/article/details/125940912 从github上面clone项目&#xff0c;出现下图问题&#xff1a; 解决问题&#xff1a; 我这个的情况是因为多文件嵌套了&#xff0c;我用Android Studio打开的是A文件&#xff0c;而B项…

oracle adg dup 一拖一拖一(一主两备)(dup)

oracle adg dup 一拖一拖一&#xff08;一主两备&#xff09; 1.配置Public IP ora1 nmcli connection modify ens33 ipv4.addresses 192.168.134.249/24 ipv4.gateway 192.168.134.2 ipv4.method manual autoconnect yes nmcli connection up ens33 nmcli connection show o…

金蝶云星空与旺店通·企业版对接集成采购入库查询打通创建采购入库单

金蝶云星空与旺店通企业版对接集成采购入库查询打通创建采购入库单 数据源系统:金蝶云星空 金蝶K/3Cloud&#xff08;金蝶云星空&#xff09;是移动互联网时代的新型ERP&#xff0c;是基于WEB2.0与云技术的新时代企业管理服务平台。金蝶K/3Cloud围绕着“生态、人人、体验”&…

嵌入式学习记录5.18(多点通信)

一、套接字属性设置相关函数 #include <sys/types.h> /* See NOTES */#include <sys/socket.h>int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname,const void *op…

Python批量docx或doc文档转换pdf

说明&#xff1a; 1、因为项目需要&#xff0c;需要手动将十几个word文档转换成pdf文档 2、python请安装3.9.0以上&#xff0c;否则一些依赖库无法正常用 #! /usr/bin/python3 # -*- coding: utf-8 -*-import os import comtypes.client# 批量将docx文件转换pdf文件 def docx_t…

1109 擅长C(测试点0,1,2,3)

当你被面试官要求用 C 写一个“Hello World”时&#xff0c;有本事像下图显示的那样写一个出来吗&#xff1f; ..C.. .C.C. C...C CCCCC C...C C...C C...C CCCC. C...C C...C CCCC. C...C C...C CCCC. .CCC. C...C C.... C.... C.... C...C .CCC. CCCC. C...C C...C C...C C…

【马蹄集】— 百度之星 2023

BD202301公园 可以先 b f s bfs bfs统计一下 t , f t,f t,f到达每个点的距离&#xff0c;还有 n n n到达其他点的距离即其他点到达 n n n的距离 然后枚举每个点 直接计算得到最小值即可 注意特判有人无法到达 n n n的情况 code: #include<bits/stdc.h> #define endl \n…

品牌做电商控价的原因

品牌控价确实是一项至关重要的任务&#xff0c;它关乎着品牌形象、市场定位以及长期发展的稳定性。在电商平台上&#xff0c;价格的公开性和透明度使得消费者、经销商和其他渠道参与方都能够轻易地进行价格比较。因此&#xff0c;品牌方必须对电商渠道的价格进行严格的管控&…

电商API接口助力直播带货选品||助力电商平台搭建选品

如今&#xff0c;直播带货如火如荼。直播带货的核心是卖货、品牌盈利&#xff0c;那想要带货效果更好&#xff0c;选品及定价是最关键的环节。 事实上&#xff0c;品牌企业可以直接使用API接口工具来辅助自身选品及定价&#xff0c;这主要是因为比价工具在直播带货选品环节能起…

因智而兴 向“新”而行 | 软通动力携子公司鸿湖万联亮相数字中国建设峰会·智算云生态大会

5月23日至27日&#xff0c;第七届数字中国建设峰会在福州盛大召开。作为峰会的重要组成部分&#xff0c;由中国电信、中国电科、中国电子联合主办的第三届智算云生态大会同步召开。此次大会以“国云注智 聚力向新”为主题&#xff0c;深入探讨了智算云、人工智能、数据要素、量…

干货!渗透测试入门教程!(建议收藏)

渗透测试是指从内网、外网等网络环境中&#xff0c;利用各种手段对某个特定网络进行模拟攻击&#xff0c;目的是为了寻找可能被利用的漏洞&#xff0c;是企业中重要的一环、 虽然大多数人在学习后都能快速上手&#xff0c;但渗透测试还是有一定的门槛&#xff0c;今天就给大家…

电脑重要文件如何加密保护?教你两种方法

加密是保护电脑重要文件的常见方法&#xff0c;可以有效避免文件数据泄露。那么&#xff0c;电脑重要文件该如何加密保护呢&#xff1f;下面小编就来教你两种方法&#xff0c;帮助你解决文件安全问题。 超级加密3000 超级加密3000是一款专业的电脑数据加密软件&#xff0c;可以…

自定义CSS属性(@property)解决自定义CSS变量无法实现过渡效果的问题

且看下面的代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>demot</title&g…

幼儿园老师投稿渠道

幼儿园老师投稿通常指的是教师为了分享自己的教学经验、教育活动设计、儿童发展研究等内容&#xff0c;向专业杂志、教育平台或在线论坛提交文章或资料的过程。以下是一些关于幼儿园老师投稿的步骤和建议&#xff1a; 一、准备工作 选择合适的平台 研究不同平台的读者群体&a…

大连瓦房店市科工局副局长乔宽一行调研蓝卓

日前&#xff0c;瓦房店市科技和工业信息化局副局长乔宽、副局长国海军、轴承协会秘书长高钧一行莅临蓝卓调研&#xff0c;学习浙江数字经济发展路径&#xff0c;考察蓝卓数字化服务能力。蓝卓副总经理陈挺、装备汽配军团总监陈伟亮、数字化咨询总监周立斌、大连区域方案经理龚…

手机信息恢复:应对数据丢失的策略与技术

由于各种原因&#xff0c;我们经常会遭遇到手机数据丢失的困境。如何有效地应对数据丢失&#xff0c;找回那些对我们来说至关重要的信息&#xff1f;这就需要我们了解和掌握手机信息恢复的策略与技巧。本文将为您揭示信息数据恢复的奥秘&#xff0c;介绍应对数据丢失的实用方法…

视频号小店脱颖而出,一跃成为电商黑马!马化腾要实现电商梦了?

大家好&#xff0c;我是喷火龙。 视频号这个名字在电商的圈子里是经常被提起的&#xff0c;特别是从今年开始&#xff0c;很多之前的电商项目不行&#xff0c;加上传统电商平台开始走下坡路&#xff0c;于是很多电商人都把视频号小店作为一个新的突破口。 因为视频号小店足够…

mySQL事务、存储引擎

什么是事务&#xff0c;事务特性————>保证数据完整性 1,事务是作为单个逻辑工作单元执行的一些列操作。 2,多个操作为一个整体向系统提交&#xff0c;要么执行&#xff0c;要么都不执行。 3,事务是一个不可分割的工作逻辑单元。 事务四特性&#xff1a; 原子性atomi…

假如有几十个请求,如何去控制高并发?

公司项目中做图片或文件批量下载&#xff0c;每次下载都是大批量的&#xff0c;那么假如我一次性下载几十个&#xff0c;如何去控制并发请求的&#xff1f; 让我想想&#xff0c;额~&#xff0c; 选中ID&#xff0c;循环请求&#xff1f;&#xff0c;八嘎&#xff01;肯定不是那…