07 - JavaSE之容器

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本章宗旨:1136 -- 1个图 1个类 3个知识点 6个接口容器J2SDK 所提供的容器 API 位于 java.util 包内。容器 API 的类图如下:Collection 接口的子接口分为:Set接口(包含 HashSet类) + List接口(包含LinkedList 类和 ArrayLis t类)Map接口:包含HashMap类Set接口和List接口定义了不同的数据存储方式:Set 中的数据对象没有顺序并且不可以重复。

本章宗旨:1136 -- 1个图 1个类 3个知识点 6个接口

容器

  • J2SDK 所提供的容器 API 位于 java.util 包内。

  • 容器 API 的类图如下:

img_ff44d593ea534a0e63eba9fccba8ae9f.jpe

Collection 接口的子接口分为:Set接口(包含 HashSet类) + List接口(包含LinkedList 类和 ArrayLis t类)
Map接口:包含HashMap类

Set接口和List接口定义了不同的数据存储方式:

  1. Set 中的数据对象没有顺序并且不可以重复。
  2. List 中的数据对象有顺序并且可以重复。
  • Map接口定义了存储“键(key)——值(value)映射”的方法。

Collection接口

  • Collection接口中所定义的方法:

    int size()
    boolean isEmpty()
    void clear()
    boolean contains(Object element)
    boolean add(Object element)
    boolean remove(Object element)
    Iterator iterator()
    boolean containsALL(Collection c)
    boolean addALL(Collection c)
    boolean removeALL(Collection c)
    boolean retainALL(Collection c)
    Object[] toArray()
    AI 代码解读

举例1:

import java.util.*;
public class Test {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        // 可以放入不同类型的对象
        c.add("Hello");
        c.add(new String("World"));
        c.add(new Integer(100));
        System.out.println(c.size());
        System.out.println(c);
    }
}
// 3
// [Hello, World, 100]
AI 代码解读

举例2:

import java.util.*;
public class Test {
    public static void main(String[] args) {
        Collection c = new HashSet();
        c.add("Hello");
        c.add(new String("World"));
        c.add(new Integer(100));
        // 可以删除因为HashSet重写了equals方法。
        c.remove("Hello"); 
        c.remove(new Integer(100));
        System.out.println(c.size());
        System.out.println(c);
    }
}
// 1
// [100]
AI 代码解读
  • 容器类对象在调用 remove,contains 等方法时需要比较对象是否相等,这会涉及到对象类型的 equals 方法和 hashcode 方法;对于自定义的类型,需要重写 equals 和 hashCode 方法以实现自定义的对象相等规则。
  • 相等的对象应该具有相同的 hash codes,但是 hashCode 只在这个对象作为索引、键值的时候使用此方法,其他时候虽然不用,但是还是要重写此方法,至于重写此方法的具体实现可以随便写(比如我直接返回0也是可以的)。

Iterator 接口

  • 所有实现了 Collection 接口的容器类都有一个 iterator 方法,这个方法返回一个实现了 Iterator 接口的对象。

  • 这个 Iterator 对象称为迭代器,用以方便的实现对容器内的元素的遍历操作。

  • Iterator 接口定义了如下方法:

boolean hasNext(); // 判断游标右边是否有元素
Object next(); // 返回游标右边的元素并移动游标到下一个位置
void remove(); // 删除游标左边的元素,在执行完next之后,该操作只能执行一次
AI 代码解读

举例1:

import java.util.*;
public class Test {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add("Hello");
        c.add(new String("World"));
        c.add(new Integer(100));
        
        Iterator i = c.iterator();

        while(i.hasNext()) {
            System.out.println(i.next());
        }
    }
}
AI 代码解读
  • Iterator 对象的 remove 方法是在迭代过程中删除元素的唯一的安全方法。(不能使用 Collection 对象的 remove 方法,因为管家Iterator 对象在迭代过程中会将元素上锁,外人无法访问。)
import java.util.*;
public class Test {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add("Hello");
        c.add(new String("World"));
        c.add(new Integer(100));
        
        Iterator i = c.iterator();

        for(Iterator i = c.iterator(); i.hasNext(); ) {
            if(i.next().equals(100)) {
                i.remove();
            }
        }
        System.out.println(c); // [Hello, World]
    }
}
AI 代码解读

补充:JDK1.5 增强的 for 循环

  • 增强的 for 循环对于遍历 array 或者 Collection 的时候相当简便。
import java.util.*;

public class EnhancedFor {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        for(int i : arr) {
            System.out.println(i);
        }
        
        Collection c = new ArrayList();
        c.add(new String("aaa"));
        c.add(new String("bbb"));
        c.add(new String("ccc"));
        for(Object o : c) {
            System.out.println(o);
        }
    }
}
AI 代码解读
  • 增强型 for 循环的缺陷:(除了简单遍历外,不建议使用增强 for 循环)
  1. 对于数组:不能方便的访问下标值。
  2. 对于 Iterator ,不能方便的删除集合中特定的元素。

Set 接口

  • Set接口是 Collection 的子接口,Set 接口没有提供额外的方法,实现Set接口的容器类中的元素是没有顺序的,而且不可以重复
  • Set容器可以与数学中的“集合”概念相对应。
  • JDK API中所提供的Set容器类有HashSet,TreeSet等。

举例1:

public static void main(String[] args) {
  Set s = new HashSet();
  s.add("hello");
  s.add("world");
  s.add("world"); // 相同的元素不会被加入,类似数学的集合概念
  System.out.println(s); // [hello, world]
}
AI 代码解读

举例2:

public static void main(String[] args) {
  Set s1 = new HashSet();
  Set s2 = new HashSet();
  s1.add("a");s1.add("b");s1.add("c");
  s2.add("d");s2.add("a");s2.add("b");
  Set sn = new HashSet(s1);
  Set su = new HashSet(s1);
  sn.retainAll(s2);
  su.addAll(s2);
  System.out.println(sn); // [a, b]
  System.out.println(su); // [d, a, c, b]
}
AI 代码解读

List 接口

  • List接口是 Collection的 子接口,实现List接口的容器类中的元素是有顺序的,而且可以重复。
  • List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
  • JAVA SDK提供的List容器类有 ArrayList,LinkedList等。
Object get(int index) // 返回index位置的元素
// 返回值为Object,表示set替换掉的元素,返回出来
Object set(int index, Object element) 
void add(int index, Object element)
Object remove(Object o)
int indexOf(Object o)
int lastIndexOf(Object o)
AI 代码解读

举例:

List l1 = new LinkedList();
for(int i=0; i<6; i++) {
  li.add("a" + i);
} // [a0, a1, a2, a3, a4, a5, a6]
System.out.print((String)l1.get(2) + " "); // a2
System.out.println(li.indexOf("a3")); // 3
li.remove(1);
System.out.println(l1); // [a0, a2, a3, a4, a5, a6]
AI 代码解读

List 常用算法(Collections类)

  • Collections类提供了一些静态方法实现了基于List容器的常用算法。
void sort(List) // 对List容器内的元素排序
void shuffle(List) // 对List容器内的元素进行随机排列
void reverse(List) // 对List容器内的元素进行逆序排列
void fill(List, Object) // 用特定的List元素列表填充整个List容器
void copy(List dest, List src) 
void binarySearch(List, Object) // 对于顺序的List容器,采用二分法查找指定对象
AI 代码解读

Comparable 接口

问题:上面的算法根据什么确定容器中对象的“大小”顺序?

其实,所有可以排序的类都实现了 java.lang.Comparable 接口,Comparable河口中只有一个方法:

public int compareTo(Object obj);
AI 代码解读

该方法:

返回0表示: this == obj

返回正数表示:this > obj

返回负数表示:this < obj

实现 Comparable接口的类通过实现 compareTo 方法从而确定该类对象的排序方法。

PS:我们可以看到 compareTo 方法的参数类型是 Object 类型的,意味着如果我只想比较两只猫的话,我扔一只狗也是可以的,这就没意义了,所以在之后的 JDK 里面,将 Object 类型统一改为 泛型,这样在传入的时候就统一了比较的对象。

改写 Name 类,让其实现 Comparable 接口:

class Name implements comparable {
  //...
  public int compareTo(Object o) {
    Name n = new (Name)o;
    int lastCmp = lastName.compareTo(n.lastName); // 先比较姓氏大小
    return (lastCmp != 0 ? lastCmp : firstName.compareTo(n.firstName)); // 再比较名字大小
  }
}
AI 代码解读

改写了 compareTo 方法,相当于改写了Collections类的排序算法,至于如何排序,由你决定!


如何选择数据结构?

  • 衡量标准:读的效率和写的效率(如字符串逆序操作)
  1. Array 读快写慢(写的慢,需要另开辟数组)
  2. Linked 写快读慢(写的快,还需要改变指针指向)
  3. Hash 介于两者之间

Map接口

  • 实现Map接口的类用来存储 “键值对”
  • Map接口的实现类有 HashMap 和 TreeMap
  • Map类中存储的键值对通过键来标识,所以键的值不能重复
Object put(Object key, Object value) // 返回值为 Object,是替换掉的 value
Object get(Object key)
Object remove(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
int size()
boolean isEmpty()
void putAll(Map m)
void clear()
AI 代码解读

举例1:

import java.util.*;
public class Test {
    public static void main(String[] args) {
        Map m1 = new HashMap();
        Map m2 = new HashMap();

        m1.put("one", new Integer(1));
        m1.put("two", new Integer(2));
        m1.put("three", new Integer(3));

        m2.put("A", new Integer(1));
        m2.put("B", new Integer(2));

        System.out.println(m1.size());
        System.out.println(m1.containsKey("one"));
        System.out.println(m2.containsValue(new Integer(2)));

        if(m1.containsKey("two")) {
            int i = ((Integer) m1.get("two")).intValue();
            System.out.println(i);
        }

        Map m3 = new HashMap(m1);
        m3.putAll(m2);
        System.out.println(m3);

    }
}
AI 代码解读

举例2:

import java.util.*;
public class Test {
    private static final Integer ONE = new Integer(1);
    public static void main(String[] args) {
        Map m = new HashMap();

        for(int i=0; i<args.length; i++) {
            Integer freq = (Integer) m.get(args[i]);
            m.put(args[i], freq == null ? ONE : new Integer(freq.intValue() + 1));
        }

        System.out.println(m);

    }
}
// java Test 77 88 99 99 99 
// {77=1, 88=1, 99=3}
AI 代码解读

Auto-boxing/unboxing

  • 在合适的时机自动打包/解包
  1. 自动将基础类型转换成对象
  2. 自动将对象转换成基础类型
import java.util.*;
public class Test {
    private static final int ONE = 1;
    public static void main(String[] args) {
        Map m = new HashMap();

        for(int i=0; i<args.length; i++) {
            int freq = ((Integer) m.get(args[i]) == null ? 0 : (Integer) m.get(args[i]));
            m.put(args[i], freq == 0 ? ONE : freq + 1);
        }

        System.out.println(m);
    }
}
AI 代码解读

泛型

  • 起因
  1. JDK1.4之前类型不明确,装入集合的类型都被当做 Object 对待,从而失去了其本身的实际类型。
  2. 从集合中取出元素时需要转型,效率低,容易产生错误。
  • 解决办法
  1. 在定义集合的时候定义集合中对象的类型
import java.util.*;
public class Test {
    public static void main(String[] args) {
        Collection<String> c = new HashSet<String>();
        c.add("aaa"); c.add("bbb"); c.add("ccc");

        for(Iterator<String> i = c.iterator(); i.hasNext(); ) {
            System.out.println(i.next());
        }
    }
}
// aaa ccc bbb
AI 代码解读

总结

1136:一个图,一个类,三个知识点,六个接口

img_9b37adfe33bc1d65f77c136a8aea105f.png

daotin
+关注
目录
打赏
0
0
0
0
12
分享
相关文章
【JavaSE专栏50】Java集合类Vector解析,一款线程安全的动态数组容器
【JavaSE专栏50】Java集合类Vector解析,一款线程安全的动态数组容器
121 0
ubuntu22 编译安装docker,和docker容器方式安装 deepseek
本脚本适用于Ubuntu 22.04,主要功能包括编译安装Docker和安装DeepSeek模型。首先通过Apt源配置安装Docker,确保网络稳定(建议使用VPN)。接着下载并配置Docker二进制文件,创建Docker用户组并设置守护进程。随后拉取Debian 12镜像,安装系统必备工具,配置Ollama模型管理器,并最终部署和运行DeepSeek模型,提供API接口进行交互测试。
280 15
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
323 78
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
189 6
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
在Docker容器中运行打包好的应用程序
在Docker容器中运行打包好的应用程序
docker 是什么?docker初认识之如何部署docker-优雅草后续将会把产品发布部署至docker容器中-因此会出相关系列文章-优雅草央千澈
Docker 是一个开源的容器化平台,允许开发者将应用程序及其依赖项打包成标准化单元(容器),确保在任何支持 Docker 的操作系统上一致运行。容器共享主机内核,提供轻量级、高效的执行环境。本文介绍如何在 Ubuntu 上安装 Docker,并通过简单步骤验证安装成功。后续文章将探讨使用 Docker 部署开源项目。优雅草央千澈 源、安装 Docker 包、验证安装 - 适用场景:开发、测试、生产环境 通过以上步骤,您可以在 Ubuntu 系统上成功安装并运行 Docker,为后续的应用部署打下基础。
101 8
docker 是什么?docker初认识之如何部署docker-优雅草后续将会把产品发布部署至docker容器中-因此会出相关系列文章-优雅草央千澈
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
Docker 是一种开源的应用容器引擎,允许开发者将应用程序及其依赖打包成可移植的镜像,并在任何支持 Docker 的平台上运行。其核心概念包括镜像、容器和仓库。镜像是只读的文件系统,容器是镜像的运行实例,仓库用于存储和分发镜像。Kubernetes(k8s)则是容器集群管理系统,提供自动化部署、扩展和维护等功能,支持服务发现、负载均衡、自动伸缩等特性。两者结合使用,可以实现高效的容器化应用管理和运维。Docker 主要用于单主机上的容器管理,而 Kubernetes 则专注于跨多主机的容器编排与调度。尽管 k8s 逐渐减少了对 Docker 作为容器运行时的支持,但 Doc
199 5
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
入门级容器技术解析:Docker和K8s的区别与关系
本文介绍了容器技术的发展历程及其重要组成部分Docker和Kubernetes。从传统物理机到虚拟机,再到容器化,每一步都旨在更高效地利用服务器资源并简化应用部署。容器技术通过隔离环境、减少依赖冲突和提高可移植性,解决了传统部署方式中的诸多问题。Docker作为容器化平台,专注于创建和管理容器;而Kubernetes则是一个强大的容器编排系统,用于自动化部署、扩展和管理容器化应用。两者相辅相成,共同推动了现代云原生应用的快速发展。
267 11
实战~如何组织一个多容器项目docker-compose
本文介绍了如何使用Docker搭建Nginx、PHP和MySQL的环境。首先启动Nginx容器并查看IP地址,接着启动Alpine容器并安装curl测试连通性。通过`--link`方式或`docker-compose`配置文件实现服务间的通信。最后展示了Nginx配置文件和PHP代码示例,验证了各服务的正常运行。
102 3
实战~如何组织一个多容器项目docker-compose