理解Java中的Bag ADT:一种灵活的数据结构
从现在开始,我们要努力学习啦!今天我给大家带来《理解Java中的Bag ADT:一种灵活的数据结构》,感兴趣的朋友请继续看下去吧!下文中的内容我们主要会涉及到等等知识点,如果在阅读本文过程中有遇到不清楚的地方,欢迎留言呀!我们一起讨论,一起学习!
本文介绍了 java 中的 bag 抽象数据类型 (adt),重点介绍了它处理具有重复元素和动态调整大小的无序集合的能力。通过详细的实现示例,它演示了 bag adt 如何提供有效的解决方案来管理库存系统等实际应用程序中的集合。
在计算机科学中,抽象数据类型(adt)对于管理和组织数据至关重要。它们可以被定义为“描述数据集以及对该数据的操作的规范”(carrano & henry,2018)。在java中,adt广泛用于包、栈、队列、集合等集合的开发。本文重点介绍 bag adt,它允许重复元素、支持动态调整大小并提供处理无序集合的灵活性。 java 中的 bag 类型是属于 collection 类的基本数据类型,见图 1。
图1
可更新集合
注意:链接缓冲区是 updatablebag 的实现,由任意数量的保存元素的缓冲区组成,排列在列表中。每个缓冲区保存一个元素数组。 arbtree 是 updatablebag 的实现,elementsortedcollection 实现红黑树,一种平衡排序二叉搜索树的形式。摘自 lee (n. d.) 的收藏包概述。
bag 的属性可以定义如下:
- 重复 — 允许重复。
- 无序 — bag 元素未排序。
- 动态调整大小 — 大小可以动态更改。
- 可迭代——在 java 中,包是可以迭代的。
- 无索引 — 包元素未建立索引。
- 高效的添加操作 - 将元素添加到包中通常是 o(1) 操作。
- 支持集合操作。见图2。
- 通用类型——包可以容纳任何类型的元素。
- 没有键值对 — 包存储没有关联键的元素。
- 可变 — 包的内容在创建后可以更改,可以动态调整大小。
- 支持空元素 - 包可能允许空元素。
图2
包类 uml
注意:来自 carrano 和 henry 的《data structures and abstractions with java》(第五版)(2018 年)。
在 java 编程语言的上下文中,堆栈、队列、
- linkedlist、set 和 bag 可以描述如下:
- 堆栈是具有特定删除顺序的元素集合的adt = lifo(后进先出),允许重复。
- 队列是具有特定移除顺序的元素集合的adt = fifo(先进先出),允许重复。
- linkedlist 是列表的实现。
- set 是元素集合的 adt,不允许重复。
- bag是允许重复的元素集合的adt。
换句话说,任何包含元素的集合都是collection,任何允许重复的集合都是bag,否则就是set。 (马托尼,2017)
bag 的主要好处是它允许重复和迭代,它也是可变的,允许动态调整其元素的大小和修改。换句话说,“如果不需要重复项,您可以使用 set 而不是 bag。此外,如果您关心删除顺序,您会选择堆栈或队列,它们基本上是具有特定删除顺序的包。您可以将 bag 视为 stack 和 queue 的超类型,它通过特定操作扩展其 api”(matoni,2017)。下面的程序是 bag adt 方法对杂货库存的简单实现的示例。
bag 类实现 bag adt
import java.util.iterator;
import java.util.nosuchelementexception;
/**
* a simple implementation of a bag adt (abstract data type). it implements a
* linked structure systems, a chain data structure. [item | next] -> [item |
* next] -> [item | next] -> null.
*
* @param the type of elements held in this bag
*
* @author alejandro ricciardi
* @date 08/12/2024
*/
public class bag implements iterable {
private node headnode; // the first node in the bag list
private int size; // number of node in the bag
/**
* private inner class that creates a node in the linked structure. each node
* contains an item and a reference to the next node. [item | next] -> [item |
* next] -> [item | next] -> null
*
*/
private class node {
t item; // the item stored in the node
node next; // reference to the next node
}
/**
* constructs an empty bag.
*/
public bag() {
headnode = null; // initialize the first (head) node in the bag to null
(empty bag)
size = 0; // initialize size of the bag to 0
}
/**
* adds the specified item to this bag. this operation runs in constant time
* o(1).
*
* @param item the item to add to the bag
*/
public void add(t item) {
node nextnode = headnode; // save the current head node becoming the next
// node in the added node
headnode = new node(); // create a new node and make it the head node
headnode.item = item; // set the item of the new node
headnode.next = nextnode; // link the new node to the old head node
size++; // increment the size of the bag
}
/**
* removes one item from the bag if it exists. this operation runs in linear
* time o(n) in the worst case.
*
* @param item the item to remove
* @return true if the item was found and removed, false otherwise
*/
public boolean remove(t item) {
if (headnode == null)
return false; // if the bag is empty, return false
if (headnode.item.equals(item)) { // if the item is in the first node
headnode = headnode.next; // make the next node the new head node
size--; // decrement the size
return true;
}
node current = headnode;
while (current.next != null) { // iterates the linked structure
if (current.next.item.equals(item)) { // if the next node contains
// the item
current.next = current.next.next; // remove the next node from
// the chain
size--; // decrement the size
return true;
}
current = current.next; // move to the next node
}
return false; // item not found in the bag
}
/**
* returns the number of items in this bag.
*
* @return the number of items in this bag
*/
public int size() {
return size;
}
/**
* checks if this bag is empty.
*
* @return true if this bag contains no items, false otherwise
*/
public boolean isempty() {
return size == 0;
}
/**
* returns an iterator that iterates over the items in this bag.
*
* @return an iterator that iterates over the items in this bag
*/
public iterator iterator() {
return new bagiterator();
}
/**
* private inner class that implements the iterator interface.
*/
private class bagiterator implements iterator {
private node current = headnode; // start from the first (head) node
/**
* checks if there are more elements to iterate over.
*
* @return true if there are more elements, false otherwise
*/
public boolean hasnext() {
return current != null;
}
/**
* returns the next element in the iteration.
*
* @return the next element in the iteration
* @throws nosuchelementexception if there are no more elements
*/
public t next() {
if (!hasnext())
throw new nosuchelementexception();
t item = current.item; // get the item from the current node
current = current.next; // move to the next node
return item;
}
}
}
groceryinventory 使用 bag adt 方法实现了一个简单的杂货店库存管理系统:
/**
* a simple grocery store inventory management system using a bag adt.
*
* @author alejandro ricciardi
* @date 08/12/2024
*/
public class groceryinventory {
// the bag adt used to store items
private bag inventory;
/**
* constructs a new grocoryinventory
*/
public groceryinventory() {
inventory = new bag<>();
}
/**
* adds items to the inventory.
*
* @param item the name of the item to add.
* @param quantity the number of items to add.
*/
public void addshipment(string item, int quantity) {
// add the item to the bag 'quantity' times
for (int i = 0; i < quantity; i++) {
inventory.add(item);
}
}
/**
* removes item from the inventory.
*
* @param item the name of the item to remove.
* @return true if the item was successfully removed, false otherwise.
*/
public boolean sellitem(string item) {
return inventory.remove(item);
}
/**
* counts the number of a specific item in the inventory (duplicates).
*
* @param item the name of the item to be counted.
* @return the number of this item in the inventory.
*/
public int getitemcount(string item) {
int count = 0;
// iterate through the bag and count the number of the given item in it
for (string s : inventory) {
if (s.equals(item)) {
count++;
}
}
return count;
}
/**
* main method.
*/
public static void main(string[] args) {
groceryinventory store = new groceryinventory();
// add inventory
store.addshipment("apple", 50);
store.addshipment("banana", 30);
store.addshipment("orange", 40);
// initial apple count
system.out.println("apples in stock: " + store.getitemcount("apple"));
// selling apples
store.sellitem("apple");
store.sellitem("apple");
// apple count after selling
system.out.println("apples after selling 2: " +
store.getitemcount("apple"));
}
}
输出
Apples in stock: 50 Apples after selling 2: 48
bag adt 在这个例子中很有用,因为它是可迭代的,它可以存储同一对象的多个实例(例如,像苹果这样的重复项),并创建一个抽象来简化对项目数据的操作,并且不需要项目待订购。与数组不同,bag 不需要固定大小,可以根据需要动态调整大小。此外,它们(对于本示例)比列表更好,因为它们不需要订购物品(例如,苹果可以存储在香蕉之后或之前)。此外,它们比 sets 更好(对于本例),因为它们允许重复(例如,您可以在商店里拥有多个苹果)。
换句话说,在这个例子中很有用并且更好,因为:
- 您可以轻松添加多个苹果或香蕉 (addshipment)。
- 您可以在单个商品售出后将其移除 (sellitem)。
- 您可以计算您拥有的每件物品的数量 (getitemcount)
总之,java 中的 bag adt 是一种灵活且高效的管理元素集合的方法,特别是在需要重复和动态调整大小时。它是一个简单但功能强大的结构,允许轻松添加、删除和迭代元素,使其成为库存系统等应用程序的理想选择,如杂货店示例所示。
参考文献:
carrano, f.m. 和 henry, t.m.(2018 年,1 月 31 日)。 java 的数据结构和抽象(第五版)。皮尔逊。
lee, d. (n. d.)。收藏包概述 [doug lea 的主页]。纽约州立大学计算机科学系。 https://gee.cs.oswego.edu/dl/classes/collections/
马托尼(2017 年,4 月 15 日)。在 java 中使用 bag 的原因 [post]。堆栈溢出。 https://stackoverflow.com/questions/43428114/reasons-for-using-a-bag-in-java
最初于 2024 年 10 月 3 日发表于 alex.omegapy - medium。
今天关于《理解Java中的Bag ADT:一种灵活的数据结构》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!
将 Playwright 与 Jenkins 集成的最佳实践是什么
- 上一篇
- 将 Playwright 与 Jenkins 集成的最佳实践是什么
- 下一篇
- Go语言如何实现PHP关联数组的功能?
-
- 文章 · java教程 | 1星期前 | map · 并发安全 · 缓存设计 · Java教程 · java optional concurrenthashmap computeIfAbsent Map缓存
- Java computeIfAbsent 缓存初始化实战:少写判断、避开空值和并发坑
- 236浏览 收藏
-
- 文章 · java教程 | 1星期前 | Java · 异步编程 · 后端开发 · CompletableFuture · 接口聚合 · java 结果合并 completablefuture 并行调用 超时兜底
- Java CompletableFuture 多接口聚合完整流程:并行调用、超时兜底和结果合并
- 428浏览 收藏
-
- 文章 · java教程 | 1星期前 | Java · 线程安全 · DateTimeFormatter · 日期处理 · 并发问题 · java 线程安全 日期格式化 threadlocal SimpleDateFormat DateTimeFormatter
- Java SimpleDateFormat 日期偶发错乱怎么办:从共享实例到线程安全一步步排查
- 481浏览 收藏
-
- 文章 · java教程 | 1星期前 | http接口 · httpclient · Java教程 · 接口调试 · 超时处理 · java 接口调用 httpclient 超时控制 状态码 响应体
- Java HttpClient 调接口实战:超时、状态码和响应体这样处理
- 224浏览 收藏
-
- 文章 · java教程 | 1星期前 | 时间处理 · instant · Java教程 · 时区转换 · DateTimeFormatter · java DateTimeFormatter java.time 时区处理 ZoneId INSTANT
- Java 时间与时区处理实战:Instant、ZoneId 和 DateTimeFormatter 怎么配
- 461浏览 收藏
-
- 文章 · java教程 | 1星期前 | Java · Stream · 集合统计 · 分组聚合 · Collectors · java Stream Collectors groupingBy counting summarizingInt
- Java Stream 分组统计实战:groupingBy、counting 和 summarizingInt 怎么用
- 478浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ljg-skills
- ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
- 1826次使用
-
- MELO音乐
- MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
- 1747次使用
-
- UniScribe
- UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
- 1696次使用
-
- 剧云
- 剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
- 1890次使用
-
- 万象有声
- 万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
- 1875次使用
-
- 矩阵主副对角线快速定位技巧
- 2026-05-31 501浏览
-
- Java多态优化流程代码与行为分发改进
- 2026-05-26 501浏览
-
- JVM 类元数据双亲委派链表深度解析
- 2026-05-21 501浏览
-
- 反射异常处理:InvocationTargetException解析与应用
- 2026-05-16 501浏览
-
- 怎么通过 HTML 的 accesskey 属性为网页中的按钮或链接设置键盘快捷键
- 2026-05-04 501浏览

