Java进阶-容器-程序员宅基地

技术标签: java  数据结构与算法  

Java中有一些对象被称为容器(container)。容器中可以包含多个对象,每个对象称为容器中的一个元素。容器是用对象封装的数据结构(data structure)。

 

充满梦想的容器

不同的数据结构有不同的组织元素的方式,也可以有不同的操作。根据具体实施的不同,数据结构的操作效率也各有差别。Java中的容器也是这样。我们要选择适当的容器,以应对变化的需求。

(关于数据结构更多的内容,可参考纸上谈兵: 算法与数据结构)

 

数组

数组(array)是最常见的数据结构。数组是相同类型元素的有序集合,并有固定的大小(可容纳固定数目的元素)。数组可以根据下标(index)来随机存取(random access)元素。在内存中,数组通常是一段连续的存储单元。

Java支持数组这一数据结构。我们需要说明每个数组的类型和大小。如下:

public class Test {
	public static void main(String[] args) {
		Human[] persons = new Human[2]; // array size 2
		persons[0] = new Human(160);
		persons[1] = new Human(170);

		int[] a = { 1, 2, 3, 7, 9 }; // array size 5
		System.out.println(a[2]);

		String[] names = { "Tom", "Jerry", "Luffy" }; // array size 3
		System.out.println(names[0]);
	}
}

在说明类型时,在类型说明(Human)后面增加一个[],来说明是一个数组。使用new创建容器时,需要说明数组的大小。

我们可以使用 数组名[下标] 的方式来调用某个元素。我们可以逐个的初始化数组的元素,也可以在声明的同时使用{}初始化数组。

对于非基本类型的数组,比如Human[],数组中存储的是对象的引用。

 

我们可以调用System.arraycopy()方法来有效的复制数组:

public class Test {
	public static void main(String[] args) {
		int[] aFrom = { 1, 2, 3, 7, 9 }; // array size 5
		int[] aTo = new int[3];
		System.arraycopy(aFrom, 1, aTo, 0, 3);
		System.out.println(aTo[1]);
	}
}

System.arraycopy()中,aFrom为想要复制出去的数组,aTo为想要复制到的数组,1为aFrom的想要复制出去的元素起始位置,0为aTo中想要存储复制来元素的起始位置,3为所要复制的元素总数。

 

Collection

表(List)集合(Set)是java.util中定义的两个接口(interface)。这两个接口都继承自Collection接口。通过实施接口,我们可以获得相应的容器。

我们之前都是使用类(class)来说明引用的类型。事实上,我们也可以用接口(interface)来说明引用的类型。该类型引用所指向的对象必须实施了该接口

 

我们先来使用表(List)容器。List是有序的元素集合,所以可以使用下标来说明元素的位置。集合中的元素可以相等:

import java.util.*;

public class Test {
	public static void main(String[] args) {
		List<String> l1 = new ArrayList<String>();
		l1.add("good");
		l1.add("bad");
		l1.add("shit");
		l1.remove(0);
		System.out.println(l1.get(1));
		System.out.println(l1.size());
	}
}

当我们在定义接口和创建容器时,我们使用<class>的方式来说明容器中所能容纳元素的类型。我们将只能在容器中放入class类及其衍生类的对象。

容器的引用为List类型,但容器的实施为ArrayList类。这里是将接口与实施分离。事实上,同一种抽象数据结构(ADT)都可以有多种实施方法(比如栈可以实施为数组和链表)。这样的分离允许我们更自由的选择ADT的实施方式。

我们可以定义<Object>类型的容器。由于Java中的所有类都继承自Object类,这样的容器实际上可以放入任意类型的对象。

在上面的程序中,容器为String类型。我们用

  • add()方法加入新的元素

  • get()方法可以获取容器中的元素,传递一个整数下标作为参数

  • remove()方法可以删除容器中的元素,传递一个整数下标作为参数。(有另一个remove(),传递元素自身作为参数)

  • size()方法用来返回容器中元素的总数。

List的官方文档

 

集合(set)也是元素的集合。集合中不允许有等值的元素,集合的元素没有顺序:

import java.util.*;

public class Test {
	public static void main(String[] args) {
		Set<Integer> s1 = new HashSet<Integer>();
		s1.add(4);
		s1.add(5);
		s1.add(4);
		s1.remove(5);
		System.out.println(s1);
		System.out.println(s1.size());
	}
}

重复加入的元素4只被放入容器一次。由于Set是无序的,在remove()中,我们直接传递目标元素本身作为参数。

Set的官方文档

 

 

List和Set都继承自Collection接口。Collection代表了对象的集合。上面List和Set接口中的许多方法实际上继承自Collection,比如:

add("good")        加入元素

size()             返回元素的总数

contains("bad")    是否包含元素

remove("good")     删除元素

Collection的官方文档

 

Collection还有一个iterator()的方法。该方法将Collection容器封装成循环器(Iterator)。循环器是元素的集合,它有next()方法,用于每次返回一个元素,直到循环器中元素穷尽。

import java.util.*;

public class Test {
	public static void main(String[] args) {
		List<Integer> l1 = new ArrayList<Integer>();
		l1.add(4);
		l1.add(5);
		l1.add(2);
		Iterator i = l1.iterator();
		while (i.hasNext()) {
			System.out.println(i.next());
		}
	}
}

Iterator的官方文档

 

Map

Map是键值对的集合。Map中的每个元素是一个键值对,即一个键(key)和它对应的对象值(value)。对于Map容器,我们可以通过键来找到对应的对象。

哈希表是Map常见的一种实施方式,参考纸上谈兵: 哈希表 (hash table)

 

我们需要声明Map的键和值的类型。我们下面实施一个HashMap:

import java.util.*;

public class Test {
	public static void main(String[] args) {
		Map<String, Integer> m1 = new HashMap<String, Integer>();
		m1.put("Vamei", 12);
		m1.put("Jerry", 5);
		m1.put("Tom", 18);
		System.out.println(m1.get("Vamei"));

	}
}

在Map中,我们使用put()方法来添加元素,用get()方法来获得元素。 

 

Map还提供了下面的方法,来返回一个Collection:

keySet()  将所有的键转换为Set

values()  将所有的值转换为List

 

总结

Java中,容器的接口与实施分离。这给了Java程序员更大的选择自由,当然,也为编程增加了难度。

接口为我们提供了合法的操作。在效果层面上看,不同的实施都有相同的效果。当然,不同的情境下,实施的细节将决定运行效率。

最后,是我们提到的各个类与接口的关系:

 

By Facker:

package blogjava;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Test {
	public static void main(String[] args) {
		// (List)容器。List是有序的元素集合,所以可以使用下标来说明元素的位置。集合中的元素可以相等
		List<Integer> l1 = new ArrayList<Integer>();
		// 加List数据
		l1.add(4);
		l1.add(5);
		l1.add(2);
		// 集合(set)也是元素的集合。集合中不允许有等值的元素,集合的元素没有顺序
		Set<String> l2 = new HashSet<String>();
		// 加Set数据
		l2.add("dad2");
		l2.add("dada");
		/* Map是键值对的集合。Map中的每个元素是一个键值对,即一个键(key)和它对应的对象值(value)。
		对于Map容器,我们可以通过键来找到对应的对象。*/
		Map<String, Integer> l3 = new HashMap<String, Integer>();
		// 加Map数据
		l3.put("dad", 2323);

		/* iterator()的方法。该方法将Collection容器封装成循环器(Iterator)。
		循环器是元素的集合,它有next()方法,用于每次返回一个元素,直到循环器中元素穷尽。*/
		Iterator i = l1.iterator();
		while (i.hasNext()) {
			System.out.println(i.next());
		}
		Iterator i2 = l2.iterator();
		while (i2.hasNext()) {
			System.out.println(i2.next());
		}
		System.out.println(l3.get("dad"));
	}
}


转载于:https://my.oschina.net/xuliblog/blog/607281

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/choudanjing5788/article/details/101007372

智能推荐

python 读取txt文件、转为json文件_python 读写txt文件 json文件的实现方法-程序员宅基地

文章浏览阅读3.6k次。首先第一步,打开文件,有两个函数可供选择:open() 和 file()①.f = open('file.txt',‘w')...file.close()②.f = file('file.json','r')...file.close()#记得打开文件时最后不要忘记关闭!open() 和 file() 都是Python的内建函数,返回一个文件对象,具有相同的功能,可以任意替换。使用语法为:f =...

AI优秘数字人克隆系统源代码:本地部署,轻松开发个性化克隆系统!”-程序员宅基地

文章浏览阅读323次,点赞3次,收藏9次。AI数字人克隆系统源代码克隆系统的开发是近年来人工智能领域的研究热点之一。这个系统的实现将赋予人工智能无限可能,为人们带来前所未有的便利和体验。一、首先理解什么是AI数字人克隆系统源代码克隆系统1、AI数字人克隆系统能够创建一个虚拟的数字人形象,使其具备与真实人类相似甚至超越的能力。源代码克隆系统作为该系统的核心部件,负责实现数字人行为和人工智能决策的复制。源代码克隆系统主要基于机器学习和深度学习的技术,通过建立大规模的数据集进行训练,使得数字人能够准确地模仿真实人类的行为。2、该系统开发的关键过程

php 跑马灯抽奖,九宫格抽奖跑马灯效果实现--微信小程序-程序员宅基地

文章浏览阅读268次。目标希得行更是u告果款近刚交易一c屏。基近刚交望实现一个九宫格跑马灯效果的抽奖功能,但希望不止局限于固定的样式或效果。考虑做成一个n*n的可自定义某些参数的组件。可自定义某些参数例如:能指定动画效果的,能局部自定义样式的自水一套还点指构框未制果定者域会通时近带货些丰是,的接架完是为广文或有过还近带货些丰是,的接架完是为广文或有过还近带货些丰是,的接架完是为广文或有过还近带货些丰是,的接架完是为广文..._9个灯随机抽取编程

真好玩python教孩子学编程_Python真好玩:教孩子学编程-程序员宅基地

文章浏览阅读140次。前言第1章 结交一个新朋友,它的名字叫Python1.1 请叫我Python大人 11.2 邀请Python来我的电脑做客 21.3 用Python指挥你的电脑 161.4 Python的第一个程序 181.5 回忆我们的朋友Python 201.6 首次小挑战 20第2章 召唤画图的小海龟2.1 认识会作图的小海龟 212.2 小海龟的作图绝学 282.2.1 小海龟画线段 282.2.2 小海..._python真好玩:教孩子学编程

网络协议栈设计(七)---网络层ARP协议分析(发送)_arp结构体的设计-程序员宅基地

文章浏览阅读533次。网络协议栈设计(七)本篇,我们就进入数据链路层的上层,网络层,看看我们在网络层需要做哪些事情。 在网路层,我们实现的协议有ARP协议,IPv4协议,ICMP协议。 学习网络协议栈的伙伴相信对于协议的内容及功能都已经有了一定的掌握,我在此不再赘述。 ARP协议处在网络层协议的最底层,为网络层其他协议服务的。按照我们自底向上的设计顺序,我们本篇,就给大家先带来ARP协议的设计。 地址解析协议,_arp结构体的设计

「 LaTeX 」写论文,IEEE论文插入作者图片IEEEbiography-程序员宅基地

文章浏览阅读1.4w次,点赞13次,收藏19次。将个人照片的pdf放到根目录下,实现代码:\begin{IEEEbiography}[{\includegraphics[width=1in,height=1.25in,clip,keepaspectratio]{Robot_Starscream.pdf}}]{Robot_Starscream}A good boy\end{IEEEbiography}效果:_ieeebiography

随便推点

上传图片并生成略缩图 _gin框架上传图片生成缩略图-程序员宅基地

文章浏览阅读466次。 上传图片并生成略缩图 参数说明FileBox:上传表单中的表单名SavePath:保存路径ThumbnailWidth:略缩图宽ThumbnailHeight:略缩图高FilePath:文件保存路径(输出参数)FileName:文件名称(输出参数)LastError:(输出错误)public static bool UploadImages(System.Web.UI.HtmlControl_gin框架上传图片生成缩略图

01. ARM Cortex-M - (02).STM32F4X7-程序员宅基地

文章浏览阅读401次,点赞10次,收藏12次。具体寄存器映射详见 STM32F4X7 手册。

【Android NDK编程--- C/C++中使用LOG输出进行跟踪】【转载】_jni c++ log-程序员宅基地

文章浏览阅读385次,点赞8次,收藏8次。前面的文章我们基本已经把NDK的基本应用全部讲完了,我们在JAVA的调试中经常会用到Log.i什么的方法进行输出跟踪,这一篇我主要来说一下在NDK开发中,C++的代码中怎么实现日志输出。从上图中我们可以看到,在Logcat的日志中已经输出我们每一步的输出,这样在调试C/C++的代码中可以通过输出方式找到哪一步出的问题,方便我们开发,提高效率。我们直接在上一章的两个数相乘的方法中进行日志输出看看结果,改造一下。我们还是用原来的那个Demo程序,按照我们的实现方法来进行。接下来我们看一下运行后的结果。_jni c++ log

基于ArrayList实现简单洗牌-程序员宅基地

文章浏览阅读1.6k次,点赞33次,收藏21次。ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表,与普通数组的区别就是它是没有固定大小的限制。

实现稀疏矩阵(采用三元组表示)的基本运算_实现稀疏矩阵(采用三元组表示)的基本运算-程序员宅基地

文章浏览阅读7.8k次,点赞11次,收藏72次。实现稀疏矩阵(采用三元组表示)的基本运算假设nxn的稀疏矩阵A采用三元组表示,设计一个程序exp4-2.cpp,完成如下功能。(1)生成如下两个稀疏矩阵的三元组a和ba=1 0 3 00 1 0 00 0 1 00 0 1 1b=3 0 0 00 4 0 00 0 1 00 0 2 0(2)输出a矩阵的三元组(3)输出b的转置矩阵的三元组代码如下//稀疏矩阵的三元组表示-算法#include <stdio.h>#define M 4#define N 4#d_实现稀疏矩阵(采用三元组表示)的基本运算

解决Xilinx官方PCIe测试程序xdma_rw.exe传输数据量受限的问题(传输超过8 MB数据时报错error code=1359)_xdma读取非8字节卡死-程序员宅基地

文章浏览阅读2.8k次,点赞8次,收藏21次。在利用Xilinx Zynq开发板进行PCIe数据传输时,经常用到XDMA这个IP,并配套Xilinx官方测试程序xdma_rw.exe进行PC到开发板的数据传输测试。可是在传输超过一定大小的数据时,就会失败。是一个叫XDMA_MAX_TRANSFER_SIZE的参数限制了传输数据量,将其修改为合适的大小即可。_xdma读取非8字节卡死