斐波那契数列java代码_深入Java HashMap新特性&&HashMap改进斐波那契数列算法

HashMap对于Java程序员来说应该非常熟悉了,这是我们项目中最常用的一个数据结构。

这篇文章我们将详细的介绍HashMap的性特性以及如何正确的使用HashMap。在我们开始深入HashMap之前,让我们先看一个简单的例子。


如果你有一家商店,商店中有琳琅满目的商品,这些商品的名称和价格都不相同,你很难记住每个商品对应的价格。所以,你需要将每个商品的名称和价格记录在纸上,每当销售这个商品的时候,你需要去纸上找到它对应的价格。

如果商品的名称不是按照顺序写在纸上的,则每次查找需要花费很长的时间。这在算法学中,我们知道它的时间复杂度是O(n)。如果名称是按照顺序写在纸上的,则可以使用二分法搜索,时间复杂度为O(log n),O(log n)花费的时间要小于O(n)。

尽管O(log n)花费的时间要小的多,但是仍然需要一定的时间。我们设想如果根本不需要时间的话,那将是是最好的情况。如果你能完全记住所有商品的名称和价格,并能在第一时间告诉买家价格,那这就是最节省时间的方法了。


现在我们回到HashMap。HashMap可以完美的解决上面的问题。

HashMap是一个Key-Value的数据结构,它的内部采用数组和链表的数据结构,所以它的查询继承了数组的线性查找,修改的时候继承了链表的寻址修改,get和put操作提供恒定的时间O(1)复杂度。它是非线程安全的,所以效率非常高。

我们现在定义个商品的HashMap,它的Key是商品的名称,Value是商品的价格。

4b6f02a0c8ac384b8d4e8f64d8d1d8f1.png

商品的HashMap

现在我们需要一个get方法来获取某个商品的价格

a3cd7108fba6db3cd2543d61b16b999d.png

获取商品的价格

以上介绍了HashMap的基础知识,我们了解了如何创建一个HashMap并如何根据key值获取value值,现在我们深入了解如何使用它

一、获取并打印HashMap的所有键和值

有以下方法可以打印HashMap的所有键和值

  • 获取并打印所有Key值
5ef882ad128a5a533d601f428c318bb0.png

获取key

或者用lambda

f4e48543b7eb0deb05b3c18dd2575704.png

lambda

  • 获取并打印所有Value值
ff5a28ff408c84ce098a5d3cd9add740.png

获取value

  • 如果我们想同时获取Key和Value值,采用以下方法
2b04b5d4f9922a0032a9157b4a1a49e9.png

获取key、value

我们也可以使用lambda

2258f54bfeed5d4fb86b692719b58367.png

lambda 获取key、value

二、斐波那契数列遇到HashMap

斐波那契数列是一个著名的数列,用于演示递归,该数列的公式如下:

f(n) = f(n - 1)+ f(n - 2)

正常的算法下,如果我们计算f(4)和f(3)的时候,可能会一遍又一遍地计算出相同的值,这样完全是对时间的浪费。如果我们使用HashMap,可以很容易地避免这一点。

e5c16141df38f93b9c76df6af598665a.png

斐波那契数列

在以上代码中,每次计算的时候,我们都先判断Map中是否已经存在斐波那契数列,如果存在,我们直接返回相应的值。这样,我们极大的提升了计算斐波那契数列的时间。接下来我们研究一下HashMap中的另外的一些方法,进一步来改进这段代码。

三、ComputeIfAbsent() 和 PuIfAbsent()

我们先不说明这两个方法的含义,我们先用这两个方法改造我们上面的代码,使它变的更为精简一些。改造后的代码如下:

64a988d4fbce1722d7de08e2953e1244.png

改进的斐波那契数列

ComputeIfAbsent方法需要两个参数,一个是key,一个是回调方法,回调方法返回的是这个key所对应的value值。所以computeIfAbsent方法的含义是:

如果map中存在这个key,返回key所对应的value值。否则,计算value的值并将key、value放入map返回value值。

PuIfAbsent方法的含义是:

如果map中存在这个key,返回key所对应的value值。否则,直接返回value值。

两者的区别是:

computeIfAbsent会计算value的值,如果map中一直找不到key,则不会返回value值的。例如上面斐波那契数列的例子,当n=2的时候,如果没有提前在map中初始化key=0和key=1的值,那他就不会返回正确的value值。如下代码所示,这段代码就会抛出异常。

fa2bf22cad5eefa36ee5f56b240412d9.png

puIfAbsent任何情况下都会返回value值。

四、Compute() 和 ComputeIfPresent()

Java HashMap还有两个方法:compute() 和 computeIfPresent()。我们先看一个统计单词出现频次的简单例子:

我们有一个长的字符串,现在我们需要统计这个字符串中特定的单词出现个次数,我们用HashMap可以这么实现:

1fa830b955b4fbcb8124fc0ed35de7d3.png


这是一个非常简单的实现,我们将需要统计的单词放入HashMap,然后循环遍历字符串,如果单词存在HashMap,则给value值加1并放入HashMap。否则,不处理。

HashMap的新特性中增加了computeIfPresent的方法,我们用computeIfPresent改写这段代码如下:

5cd63c85825c56cb5cc8889e8b7a2136.png

经过computeIfPresent优化的方法优化了很多,代码量也减少了很多。computeIfPresent方法接受一个key和一个remappingFunction,只有当map中存在key的时候,remappingFunction中的逻辑才执行。

Compute方法和ComputeIfPresent很类似,接收相同的参数。不同的地方在于compute不判断map中是否存在key,如果Key不存在map,则将key添加map中。如果我们用compute方法改造一下上面的方法,会发什么呢?大家可以讨论或者运行代码自己测试

cd015391cd5c1087768c169d9a48caa8.png

总结:

HashMap的新特性使数据访问变得更加轻松和快捷。Java8和lambda表达式的引入使的我们的代码变得优雅干净,大家可以多多使用Java 8的新特性来改进你的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值