Java全栈基础篇--集合

集合

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

特点: 长度不固定,还可以存储不同的数据(但是一般都用同一类型)

集合和数组既然都是容器,它们有啥区别呢?

  1. 数组的长度是固定的。集合的长度是可变的。

  2. 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。

集合的体系

Collection 常用的方法

基本功能
  • public boolean add(E e): 把给定的对象添加到当前集合中 。

  • public void clear() :清空集合中所有的元素。

  • public boolean remove(E e): 把给定的对象在当前集合中删除。

  • public boolean contains(E e): 判断当前集合中是否包含给定的对象。

  • public boolean isEmpty(): 判断当前集合是否为空。

  • public int size(): 返回集合中元素的个数。

  • public Object[] toArray(): 把集合中的元素,存储到数组中。

高级功能

boolean addAll(Collection<? extends E> c) 添加一个集合到当前集合 boolean removeAll(Collection<?> c) 移除一个集合元素

boolean retainAll(Collection<?> c) 两个集合都有的元素,思考元素去哪里?boolean又是什么意思? boolean containsAll(Collection<?> c) 判断当前集合是否包含指定集合的元素 一个还是所有?

集合的遍历

 public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add("hello");
        c.add("java");
        c.add("collection");

        //遍历集合
        Object[] arr = c.toArray();
       //String -> Object
        for(int i=0;i<arr.length;i++){
            String s = (String)arr[i];
            System.out.println(s);
        }
    }

terator 迭代器

迭代器的介绍

专门为集合提供遍历的一种技术

迭代器的怎么使用
 Collection c = new ArrayList();
        Student student = new Student("张三",18);
        Student student2 = new Student("李四",28);
        Student student3 = new Student("王老吉",38);

        c.add(student);
        c.add(student2);
        c.add(student3);

        Iterator iterator = c.iterator();
        while (iterator.hasNext()){
            Student s = (Student) iterator.next();
            System.out.println(s);
        }
迭代器的原理

数据结构

数据结构的有什么用?

数据结构:研究数据的存储

现实世界的存储,我们使用的工具和建模。每种数据结构有自己的优点和缺点,想想如果Google的数据用的是数组的存储,我们还能方便地查询到所需要的数据吗?而算法,在这么多的数据中如何做到最快的插入,查找,删除,也是在追求更快。

我们java是面向对象的语言,就好似自动档轿车,C语言好似手动档吉普。数据结构呢?是变速箱的工作原理。你完全可以不知道变速箱怎样工作,就把自动档的车子从 A点 开到 B点,而且未必就比懂得的人慢。写程序这件事,和开车一样,经验可以起到很大作用,但如果你不知道底层是怎么工作的,就永远只能开车,既不会修车,也不能造车。当然了,数据结构内容比较多,细细的学起来也是相对费功夫的,不可能达到一蹴而就。我们将常见的数据结构:堆栈、队列、数组、链表和红黑树 这几种给大家介绍一下,作为数据结构的入门,了解一下它们的特点即可。

常见的数据结构

数据存储的常用结构有:栈、队列、数组、链表和红黑树。我们分别来了解一下:

栈,队列

数组与链表

数组: 利于查询 ,不利于增删改

链表:不利于查询 ,利于增删改

(根据需求,选择对应的数据形式,进行存储)

List 接口的方法

void add(int index, E element)

Object get(int index)

ListIterator listIterator() 返回列表中的列表迭代器(按适当的顺序)。

Object set(int index, E element)

用指定的元素(可选操作)替换此列表中指定位置的元素。

ListIterator listIterator() : 此方法重要;不但可以正向还可以反向,还可以进行添加和修改

ConcurrentModificationException 并发修改异常

在迭代器在迭代元素时,用集合去操作,出现上现的异常

解决方法是:

迭代器在进行迭代元素时,就用迭代器去修改(包括添加)

集合遍历元素时,就用集合去修改

List 子类特点

ArrayList类

底层数组 : 查询快,增删改慢

线程不安全: 不安全,效率高

Vecktor类

底层数组 : 查询快,增删改慢

线程安全: 安全,效率低

LinkedList类

底层链表 : 查询慢,增删改快

线程不安全: 不安全,效率高

AarryList的方法使用

四种遍历

ArrayList list = new ArrayList();
        list.add("hello");
        list.add("world");
        list.add("java");

        //数组
        Object[] arr  = list.toArray();
        for(int i=0; i<arr.length;i++){
            String s = (String)arr[i];
            System.out.println(arr[i]);
        }
        //迭代器
        Iterator iterator = list.iterator();
          while (iterator.hasNext()){
              System.out.println(iterator.next());
          }
        //列表迭代器
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()){
            System.out.println(listIterator.next());
        }
        //size  get()
        for(int i=0; i<list.size();i++){
            String s = (String)list.get(i);
            System.out.println(arr[i]);
        }
Vector类特有方法

addElement(E obj)

将指定的组件添加到此向量的末尾,将其大小增加1。

elementAt(int index) 返回指定索引处的组件。

elements() 返回此向量的组件的枚举。

firstElement() 返回此向量的第一个组件(索引号为 0的项目)。

JDK升级原因:

  1. 效率

  2. 简化书写

  3. 安全

/*
        * Vector类特有的方法
        * addElement(E obj) 将指定的组件添加到此向量的末尾,将其大小增加1。   add()
          elementAt(int index)返回指定索引处的组件。   get()
          elements() 返回此向量的组件的枚举。           iterator
                 hasMoreElements()                    hasNext()
                nextElement()                         next()
            firstElement() 返回此向量的第一个组件(索引号为 0的项目)。
        * */
        Vector vector = new Vector();
        vector.addElement("hello");
        vector.addElement("world");
        vector.addElement("java");

//        for(int i=0;i<vector.size();i++){
//            System.out.println(vector.elementAt(i));
//        }
//        System.out.println(vector.firstElement());

        Enumeration enumeration = vector.elements();
        while (enumeration.hasMoreElements()){
            System.out.println(enumeration.nextElement());
        }
LinkedList类特有的方法

addFirst(E e) 在该列表开头插入指定的元素。

addLast(E e) 将指定的元素追加到此列表的末尾。

泛型

泛型: 是一种把类型明确的工作推迟到创建对象或者调用方法的时候,才去明确的特殊类型, 参数化类型,把类型当做参数一样进行传递

格式:

<数据类型>

此处数据类型只能是引用类型

好处:

1. 把运行时报的错误,提前到了编译期间
1. 避免了强制转换
1. 优化程序的设计,解决了黄色警告线

泛型的应用:

  1. 类上定义泛型

public class ObjectTool<T> {
    private T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }
}

方法上定义泛型

在方法中定义泛型,相当于可以传任意类型的参数

  public <T> void show(T t){
        System.out.println(t);
    }
  1. 接口上定义泛型

方法1

 class MyListImpl implements MyList<T>{
    @Override
    public void show(String s) {
        
    }
}

方法2

 class MyListImpl<T> implements MyList<T>{
    @Override
    public void show(T s) {
        
    }
}

泛型通配符

<?> : 任意类型

<? extends E> : 向下限定 , E及子类

<? supter E > : 向上限定 , E及父类

增加for遍历集合

语法:

for(数据类型 变量名: 数组名或集合){

}

集合遍历 ,推荐使用增加for

静态导入

注意事项:1. 方法必须是静态
        2. 注意不要和本类的方法同名,如果同名,记得加前缀,由此可见,静态导入的方式,意义不太

import static java.lang.Math.abs;
import static java.lang.Math.max;
 public static void main(String[] args) {
        System.out.println(abs(-100));
        System.out.println(java.lang.Math.max(100,200));
    }

可变参数

可变参数:定义时方法时不知道参数具体个数,可以使用此技术

格式:

修饰符 返回值 类型 方法名(数据类型... 参数名){

}

// ... 表示是可变参数

注意事项

  1. 可以了可变参数,此变量相当于是一个数组

  2. 如果方法里有多个参数,其它包含可变参数,那可变参数必须放在最后

数组转集合

Arrays.asList 此方法可以将数组转集合,但是本质还是数组,所以不能操作集合改变数组大小的方法

List<String> list = Arrays.asList("hello","world","java");
        System.out.println(list);
        System.out.println(list.get(0));
        //UnsupportedOperationException
        //list.add("java ee");
        list.set(1,"hahaha");

        for(String str:list){
            System.out.println(str);
        }

Set 接口

特点: 不包含重复的元素,无序(指的是存数据 ,和取数据的顺序是否一致)

HashSet子类

无序,唯一性

HashSet 如何实现唯一性(看源码)

HashSet 的底层是使用的HashMap

根据源码分析,得到要保证HashSet里的元素的唯一性,涉及到了Hash值 和equals方法

 

interface Collection{
   ....
}
interface Set extends Collection{
   ...
}
class HashSet implements Set{

// Collection 就相当于单身,  Map 一对夫妻
    private transient HashMap<E,Object> map;
    public HashSet() {
        map = new HashMap<>();
    }
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
}
class HashMap implements Map{
     final float loadFactor;
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
     public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }
    
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    
    
   final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
}

自定义对象,使用HashSet; 如果想实现当所有属性相同时,认为是重复,不添加;

需要重写hashcode 和 equals

去重原理

HashSet 的底层是HashMap, hashMap的底层是哈希表(数组和链表的结合)

 

 

LinkedHashSet 子类

底层数据结构:哈希表+链表

保证了唯一性,

链表保存有序(存储和取出是一致)

 

LinkedHashSet<String> hs = new LinkedHashSet<String>();
        hs.add("hello");
        hs.add("world");
        hs.add("java");
        hs.add("hello");

        for(String str :hs){
            System.out.println(str);
        }

TreeSet 子类

特点:排序 和唯一

排序 : 自然排序(就是升序)和比较器排序

public static void main(String[] args) {
        TreeSet<Integer> treeSet = new TreeSet<Integer>();
        treeSet.add(66);
        treeSet.add(18);
        treeSet.add(12);
        treeSet.add(66);
        treeSet.add(77);

        for(Integer integer: treeSet){
            System.out.println(integer);
        }
    }

Map体系

概述

现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即java.util.Map接口。

我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同,如下图。

  • Collection中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。

  • Map中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。

  • Collection中的集合称为单列集合,Map中的集合称为双列集合。

  • 需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。

Map接口中的常用方法

  • public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。

  • public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。

  • public V get(Object key) 根据指定的键,在Map集合中获取对应的值。

  • boolean containsKey(Object key) 判断集合中是否包含指定的键。

  • public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。

  • public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据可视化工具APITable:实现强大的多维表格功能并随时随地远程访问

APITable免费开源的多维表格与可视化数据库公网远程访问 文章目录 APITable免费开源的多维表格与可视化数据库公网远程访问前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台&#xff0c…

血的教训---入侵redis并免密登录redis所在服务器漏洞复现

血的教训—入侵redis并免密登录redis所在服务器漏洞复现 今天就跟着我一起来入侵redis并免密登录redis所在服务器吧&#xff0c;废话不多说&#xff0c;我们直接开始吧。 这是一个体系的学习步骤&#xff0c;当然如果基础扎实的话可以继续往下面看 以下都是关联的文章&#xff…

算法与数据结构有区别吗?

算法和数据结构并不是同一件事。严格来说&#xff0c;它们并不是等效的。但是&#xff0c;我们通常在使用的时候会互换这两个术语。为了简便&#xff0c;后文我们会用数据结构这个术语来指代“数据结构及其所有相关的方法”。 有很多方法可以用来说明这两个术语之间的区别&…

python执行shell

0x00:前言 正常一个网站分为服务端和客户端&#xff0c;因为是正向的&#xff0c;所以服务端是在目标机器上的&#xff0c;客户端则是攻击者机器上&#xff0c;在这里要感谢MiaGz大师傅&#xff0c;这里很多都是参考了MiaGz大师傅的文章写出来的&#xff0c;进行了一点个人修改…

STM32/GD32_分散加载

Q&#xff1a;如何将一个变量、某个源文件的函数在编译阶段就存储在用户指定的区域&#xff1f; KEIL环境&#xff1a;.map后缀文件、.sct后缀文件 IAR环境&#xff1a;.map后缀文件、.icf后缀文件 【map文件】 对固件里面的变量、函数、常量等元素的存储空间进行分配的说明…

【android开发-04】android中activity的生命周期介绍

1&#xff0c;返回栈 android中使用任务task来管理activity&#xff0c;一个任务就是一组存放在栈里的活动的集合&#xff0c;这个栈被称为返回栈。栈是一种先进先出的数据结构。当我们启动一个新的活动&#xff0c;他会在返回栈中人栈&#xff0c;并处以栈顶的位置&#xff0…

刘恋对话贾樟柯:焦虑往往是因为我们还有的选

11月29日&#xff0c;由房产服务国民品牌我爱我家与贾樟柯联合呈现的《住进每一种生活》&#xff0c;在乐迷和网友的热烈期盼下迎来了第三期。自首期节目在腾讯视频和极光TV播出以来&#xff0c;《住进每一种生活》频频在社交媒体上引发观众热议。 《住进每一种生活》以六位名…

指纹芯片的工作原理及应用领域详解

指纹芯片是一种利用指纹识别技术的电子设备,可以通过扫描人体指纹的纹理特征,将其转化为数字化信息并进行存储和识别。指纹芯片广泛应用于各个领域,包括智能手机、银行和金融、门禁系统、身份验证等,因其高度准确、快速便捷的特点,得到了广大用户的青睐。 指纹芯片的原理是基于…

从订阅式需求发展,透视凌雄科技DaaS模式增长潜力

订阅制&#xff0c;C端消费者早已耳熟能详&#xff0c;如今也凭借灵活、服务更新稳定的特点&#xff0c;逐渐成为B端企业服务的新热点。 比如对中小企业而言&#xff0c;办公IT设备等配套支出都必不可少&#xff0c;但收入本身并不稳定&#xff0c;购置大堆固定资产&#xff0…

【散列函数的构造方法(直接定址法 ==除留余数法==),散列表的查找(1.开放地址法,2.链地址法(拉链法))】

文章目录 散列函数的构造方法直接定址法除留余数法 散列表的查找1.开放地址法线性探测法二次探测法伪随机探测法 2.链地址法&#xff08;拉链法&#xff09; 散列表的查找效率 散列函数的构造方法 散列存储 选取某个函数&#xff0c;依该函数按关键字计算元素的存储位置。 Loc…

3.3 路由器的远程配置

实验3.3 路由器的远程配置 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施&#xff08;一&#xff09;、配置通过Telnet登录系统1.RA的基本配置2.RB的基本配置3.在RA上配置Telnet用户登录界面 &#xff08;二&#xff09;、配置通过STelnet登录系统1.RA的基本配…

SpringBoot 实现动态切换数据源,这样做才更优雅!

最近在做业务需求时&#xff0c;需要从不同的数据库中获取数据然后写入到当前数据库中&#xff0c;因此涉及到切换数据源问题。本来想着使用Mybatis-plus中提供的动态数据源SpringBoot的starter&#xff1a;dynamic-datasource-spring-boot-starter来实现。 结果引入后发现由于…

物联网实训室虚拟仿真软件建设方案

一、概述 物联网实训室虚拟仿真软件旨在紧密围绕立德树人的根本任务&#xff0c;充分依托先进的数字技术&#xff0c;并对接物联网行业的发展趋势和人才需求。通过对比真实企业工作环境&#xff0c;融合创新创业教育基因&#xff0c;秉承虚拟仿真技术与教育教学深度融合的理念&…

Linux系统iptables扩展

目录 一. iptables规则保存 1. 导出规则保存 2. 自动重载规则 ①. 当前用户生效 ②. 全局生效 二. 自定义链 1. 新建自定义链 2. 重命名自定义链 3. 添加自定义链规则 4. 调用自定义链规则 5. 删除自定义链 三. NAT 1. SNAT 2. DNAT 3. 实验 ①. 实验要求 ②. …

avue页面布局 api 引用

展示 index.vue <template><basic-container><avue-crud :option"option":table-loading"loading":data"data":page"page":permission"permissionList":search.sync"search":before-closebefore…

Linux信号超详细剖析

预备知识&#xff1a; 一、信号产生(OS发给进程) 1、键盘组合键 Linux中&#xff0c;一次登录对应一个终端&#xff0c;bash/shell。且只允许一个进程是前台进程&#xff0c;默认就是bash/shell&#xff0c;其它都是后台进程。获取键盘输入的是前台进程。 Ctrlc: 向前台进程…

KaiwuDB 亮相中国国际供应链促进博览会

11月28日&#xff0c;全球首个以供应链为主题的国家级展会——2023 中国国际供应链促进博览会&#xff08;简称“链博会”&#xff09;在北京盛大召开。KaiwuDB 受邀亮相大会&#xff0c;向与会者展示现代数据库技术在数字科技链条中的根基作用&#xff0c;其中分布式多模数据库…

mongodb连接工具

推荐几款熟悉的mongodb连接工具 mongoshellmongoCompassmongodbAtlasnosqlbooster 这四款连接工具中&#xff0c;mongoshell, mongoCompass, mongodbAtlas都是mongodb官网介绍和推荐的工具。好不好用先不说&#xff0c;这几款工具胜在官方提供&#xff0c;免费开源。无论使用怎…

Linux常用命令——axel命令

在线Linux命令查询工具 axel 多线程下载工具 补充说明 axel是Linux下一个不错的HTTP/ftp高速下载工具。支持多线程下载、断点续传&#xff0c;且可以从多个地址或者从一个地址的多个连接来下载同一个文件。适合网速不给力时多线程下载提高下载速度。比如在国内VPS或服务器上…

代码级接口测试与单元测试的区别

关于接口测试 接口测试是一个比较宽泛的概念, 近几年在国内受到很多企业和测试从业者的追捧, 尤其是上层的UI在取悦用户的过程中迭代更新加快, UI自动化维护成本急剧上升的时代, 大家便转向了绕过前端的接口层面进行测试. 但是很多人, 对接口测试的理解并不完整, 事实上, 我们…
最新文章