博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java集合的使用:List与Map
阅读量:4090 次
发布时间:2019-05-25

本文共 4762 字,大约阅读时间需要 15 分钟。

发表在

Java的容器

定义好Post类之后,现在需要对博客文章进行管理。我们可以定义一个PostRepository类,通过PostRepository可以做以下操作:

  • 创建博客
  • 删除博客
  • 获取一篇博客的内容
  • 获取博客列表

我们已经有面向对象编程的经验了,我们可以给Repository增加四个方法:

package com.tianmaying.repository;import com.tianmaying.domain.Post;public class PostRepository {    public static void add(Post post) {    }    public static Post getPostById(long id) {        return null;    }    public static void remove(long id) {    }    public static ArrayList
getAll() { return null; }}

上面我们定义了四个静态成员方法,我们刚刚讲过static修饰方法的含义,现在马上就用到了。你现在可能对getAll()方法返回的ArrayList<Post>还有点疑惑,没关系,我们马上就要讲到。

先来考虑一个问题,这个PostRepository里面应该包含什么变量呢? 我们很容易想到就是一组博客。在Java中,我们可以通过数组将一组对象组织在一起,因此我们马上可以想到定义一个Post的数组。

但是数组的尺寸是固定的,通常情况下程序总是在运行时根据条件来创建对象,我们可能无法预知将要创建对象的个数,甚至是具体的类型。比如PostRepository中保存多少Blog对象我们事先是不知道的。

这时我们就需要Java的集合(Collection)类了。我们通常也称集合为容器,因为它们可以帮我们方便地组织和管理一组对象。

所以我们可以给PostRepository类增加一个静态成员变量:

public class PostRepository {    private static posts = new ArrayList
(); ...}

这里ArrayList就是Java提供给我们使用的一个集合类,用以保存一个元素序列,并且可以进行元素的访问、插入和删除等操作。

ArrayList<Post>是一种泛型的写法。泛型就是参数化类型,即ArrayList所操作的数据类型通过一个类型参数指定。ArrayList这个容器中可以保存任何类型的变量,而且这些对象访问、插入和删除的逻辑也是相同的。比如,如果我们希望ArrayList中存放一组整数的话,我们就可以声明List<Integer>类型的变量。

在Java 7和Java 8中,编译器能够根据变量声明时的泛型类型自动推断出实例化所用的泛型类型。

ArrayList
post1 = new ArrayList
();ArrayList
post2 = new ArrayList<>();

post2的初始化就没有指定ArrayList中的泛型类型,编译器可以推导出来。

List的使用

ArrayList提供了一系列操作元素序列的方法。下面我们使用ArrayList来实现PostRepository的四个方法。

package com.tianmaying.repository;import java.util.ArrayList;import java.util.List;import com.tianmaying.domain.Post;public class PostRepository {    private static ArrayList
posts = new ArrayList
(); public static void add(Post post) { posts.add(post); } public static Post getPostById(long id) { for (Post post : posts) { if (post.getId() == id) { return post; } } return null; } public static void remove(long id) { for (Post post: posts) { if (post.getId() == id) { posts.remove(post); return; } } } public static ArrayList
getAll() { return posts; }}

我们看到ArrayList的用法很简单,可以通过add方法增加元素,通过remove方法删除元素。

遍历ArrayList的方法是一种特殊的for循环,遍历Java容器中的元素都可以使用这种方法。

我们也可以使用迭代器Iterator类来完成遍历。Iterator主要有两个方法,基于这两个方法就能进行遍历操作:

  • next()方法来获取序列的下一个元素
  • hasNext()检查序列中是否还有元素

使用Iterator实现的代码如下:

public static void remove(long id) {    Iterator
iterator = posts.iterator(); while (iterator.hasNext()) { Post post = iterator.next(); if (post.getId() == id) { posts.remove(post); return; } }}

ArrayList类似的一种容器是LinkedList,它们都是List接口的实现。接口的概念我们后面会讲,现在你只需要知道操作ArrayList和操作LinkedList的方式是完全一样的,只不过它们内部的实现机制不一样。

这两者的主要不同在于:

  • ArrayList:通过下标随机访问元素快,但是插入、删除元素较慢
  • LinkedList:插入、删除和移动元素快,但是通过下标随机访问元素性能较低

如果你学过数据结构,就是知道ArrayList是基于数组实现的,而LinkedList是基于链表实现的。这两种数据结构的特点决定了这两个容器的不同之处。

Map

Map故名思议,就是映射,可以将一个对象映射到另一个对象。每一组映射作为一个<键,值>对保存在Map容器中。MapList一样是一种接口,它的实现HashMap类,是我们最常使用的一种容器。

我们回顾getPostById这个方法的实现:

public static Post getPostById(long id) {    for (Post post : posts) {        if (post.getId() == id) {            return post;        }    }    return null;}

每次都要经过一次遍历,经过比较才能找到id对应的博客。如果能够把作为一个键值对,那么通过id取出一篇博客就更加快速和方便。现在基于Map来实现博客管理功能,我们新建另外一个类PostRepositoryByMap

package com.tianmaying.repository;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import com.tianmaying.domain.Post;public class PostRepositoryByMap {    private static Map
postsMap = new HashMap
(); public static void add(Post post) { postsMap.put(post.getId(), post); } public static Post getPostById(long id) { return postsMap.get(id); } public static void remove(long id) { postsMap.remove(id); } public static List
`addAll`方法() { List
posts = new ArrayList<>(); posts.addAll(postsMap.values()); return posts; }}`

Map具有两个泛型参数,第一个是键的类型,第二个是值的类型。类型不能是原生类型,必须是引用类型,因此这里第一个类型是long的包装类Long

使用Map之后,查找和删除博客的实现就非常简单了:

  • put方法可以增加一个键值对
  • get方法就能根据键获取到值
  • remove方法可以删除键对应的元素

Java编译器会在需要时自动帮我们进行原生数据类型和包装类之间进行转换,比如我们postMap.remove(id);这条语句传入的是long原生数据类型,Java编译器知道此时应该传入的是Long,会自动帮我们做这个转换。

我们可以获取键、值或键值对的集合,分别使用keySetvalues以及entrySetgetAll方法就通过postsMap.values()获取所有的值,这里就是所有的Blog对象。

注意这里调用了一个addAll方法,这个方法是所有容器都有的一个方法,可以把另外一个容器中的元素加入其中。

我们可以这样遍历一个Map:

for (Map.Entry
postEntry : postMap.entrySet()) { Long id = postEntry.getKey(); Post post = postEntry.getValue(); // 在遍历中操作每一个post ...}

如果PostRepositoryByMapgetAll()方法不使用addAll方法,而通过遍历的方式逐个将博客对象加入到一个List中,如何实现呢? 你可以尝试一下。

更多文章请访问

你可能感兴趣的文章
似乎写个ROS功能包并不难,你会订阅话题发布话题,加点逻辑处理,就可以写一些基础的ROS功能包了。
查看>>
if __name__ == ‘__main__‘:就是Python里的main函数,脚本从这里开始执行,如果没有main函数则从上到下顺序执行。
查看>>
PX4官方用户和开发手册的首页面是会给你选择英文和中文的
查看>>
《跟工程师学嵌入式开发》这本书最后的终极项目我反而觉得有说头
查看>>
博士的申请考核制
查看>>
MAVLink学习之路05_MAVLink应用编程接口分析(也有讲STM32下的收发函数)
查看>>
找到了中文版的mavlink手册
查看>>
浅谈飞控开发的仿真功能
查看>>
我觉得在室内弄无人机开发装个防撞机架还是很有必要的,TBUS就做得很好。
查看>>
serial也是见到很多次了,似乎它就是一种串行通信协议
查看>>
TBUS的一些信息
查看>>
专业和业余的区别就在于你在基础在基本功打磨练习花的时间
查看>>
通过mavlink实现自主航线的过程笔记
查看>>
Ardupilot飞控Mavlink代码学习
查看>>
这些网站有一些嵌入式面试题合集
查看>>
我觉得刷题是有必要的,不然小心实际被问的时候懵逼,我觉得你需要刷个50份面试题。跟考研数学疯狂刷卷子一样!
查看>>
我觉得嵌入式面试三要素:基础吃透+项目+大量刷题,缺一不可。不刷题是不行的。而且得是大量刷,刷出感觉套路,别人做题都做得是固定题型套路条件反射了,你还在那慢慢理解慢慢推是不行的,也是考研的教训。
查看>>
删除docker容器和镜像的命令
查看>>
gazebo似乎就是在装ROS的时候一起装了,装ROS的时候选择的是ros-melodic-desktop-full的话。
查看>>
React + TypeScript 实现泛型组件
查看>>