Fenrier Lab

利用 Cont Monad 封装计算

从回调方法说起 回调是一种很有效的异步编程方法,举一个简单的例子,如果我们要执行一个数据库查询语句,通常会像下面这样 Statement stat = ...; String sql = ...; ResultSet result = stat.executeQuery(sql); //后续工作 其中,后续工作可能与查询结果有关,也可能无关。如果无关的话,那么等待查询结果返回其实是不必要的,如果对性能要求比较高,那这很显然会成为瓶颈。一个比较粗糙的解决方法是把耗时操作放到另一个线程中执行 new Thread(() -> { ResultSet result = stat.executeQuery(sql); }).start(); //后续代码 ...
点我阅读更多...

Java 之美--过程封装

当我对 Java 还用得不是很熟练的时候,拥有 lambda 表达式的 jdk 8 发布了。于是怀着强烈的好奇心,去了解了一些 lambda 演算方面的知识,对于半路出家的我来说,仿佛来到了一个全新的世界。 在一开始,我并不知道如何在合适的地方去使用这个特性,仿佛它只是普通方法的一个时髦替代品而已,但我知道事实并非如此。直到后来读到了 SICP 这本书前面的章节,才算是有所领悟。可是,作为一个 Javaer,肯定还是想用 Java 来实现才会觉得踏实。下面我们就来看看,如何利用 lambda 表达式来抽象行为。 首先我们从最简单的数组求和开始 public double sum(double[] arr) { return sum(arr, 0); } private...
点我阅读更多...

Java HashMap 源码分析 01

本系列旨在深入研究 Java HashMap 的底层实现,在 JDK 9 中,HashMap 是一个拥有两千四百多行的大类,为了实现易用,强大,并且可靠的哈希表,里面有相当多的内容,希望通过这一系列文章,能对 HashMap 的实现有深入的理解。 哈希表 在具体讨论 HashMap 之前,我们先来看看哈希表这种数据结构。我们知道,数据结构是存储数据的方式,例如数组、链表这些简单的结构,而不同的数据结构对数据访问、查找、新增、删除、修改等操作的开销则存在差异,并且这种差异可能会非常巨大,于是使用不同的数据结构进行同样的编程活动,其性能差别也是非常大的,所以对数据结构的合理选择对程序的性能就至关重要。 像数组这种结构,在不考虑其容量大小的情况下,其数据访问、修改的时间复杂度为常数级 ...
点我阅读更多...

算法题:棋盘行走

在象棋规则里面,马总是按日字对角移动,现在假设有一个横向 m 条线,纵向 n 条线的棋盘,马 位于交点 (x,y) 上。如果要让马走完棋盘上的每一个点,请问有多少条路线? 这里我们先理一下思路,在棋盘上的每一个点,棋子都有 0 种,1种或者多种移动方法,如果把当前所在的点,作为一个节点,那么下一步选择要走的点其实就是在选择子节点 比如上图的马,就有6种走法,等价于有6个子节点,所有可能的移动路径用节点连接起来就成了一个图结构。棋子的每一条移动路径,都可以用图中的一条路径来表示,于是我们的问题就变成了搜索图的每一条路径,如果该路径上的节点与棋盘上的点一一对应,那么这就是一条符合条件的路线。 现在我们来考虑一下数据结构的问题。首先把棋盘上所有的点表示出来,每个点都可以用一个节点对...
点我阅读更多...

算法题:背包问题

质量约束 背包问题也是一道经典的动态规划问题,它有许多表述形式,什么劫匪小偷抢超市啦,出去旅行要打包啦,简单来说,背包问题给出了一序对集合 \(R^n=\{t_i=(w_i, v_i)\mid i=1,2,,,n\}\) ,其中 \(w_i\) 是物品总重量,\(v_i\) 是物品价值,要求从中选取总重量不超过 \(W\) 的物品,使得物品总价值 \(V\) 尽可能的大。 由于上述问题中有 \(n\) 件物品,所以将该问题定义为 \(Q^n\),假设 \(V^n\) 是该问题最优解的总价值,显然 \(V^n\) 的值与 \(R^n\) 和 \(W\) 都相关,即 \[V^n = f(W, R^n)\] 现在我们稍微缩小问题的规模,若已经从物品列表中拿取了 \(t_j\),并从限...
点我阅读更多...