链表竟然比数组慢了1000多倍?(动图+性能评测)

这是我的第 215 期分享

作者 | 王磊

来源 | Java中文社群(ID:javacn666)

转载请联系授权(微信ID:GG_Stone)

数组和链表是程序中常用的两种数据结构,也是面试中常考的面试题之一。然而对于很多人来说,只是模糊的记得二者的区别,可能还记得不一定对,并且每次到了面试的时候,都得把这些的概念拿出来背一遍才行,未免有些麻烦。而本文则会从执行过程图以及性能评测等方面入手,让你更加深入的理解和记忆二者的区别,有了这次深入的学习之后,相信会让你记忆深刻。

数组

在开始(性能评测)之前我们先来回顾一下,什么是数组?

数组的定义如下:

数组(Array)是由相同类型的元素(element)的集合所组成的数据结构,分配一块连续的内存来存储。利用元素的索引(index)可以计算出该元素对应的存储地址。

最简单的数据结构类型是一维数组。例如,索引为 0 到 9 的 32 位整数数组,可作为在存储器地址 2000,2004,2008,...2036 中,存储 10个 变量,因此索引为 i 的元素即在存储器中的 2000+4×i 地址。数组第一个元素的存储器地址称为第一地址或基础地址。

简单来说,数组就是由一块连续的内存组成的数据结构。这个概念中有一个关键词“连续”,它反映了数组的一大特点,就是它必须是由一个连续的内存组成的。

数组的数据结构,如下图所示:

数组添加的过程,如下图所示:

数组的优点

数组的“连续”特征决定了它的访问速度很快,因为它是连续存储的,所以这就决定了它的存储位置就是固定的,因此它的访问速度就很快。比如现在有 10 个房间是按照年龄顺序入住的,当我们知道第一房子住的是 20 岁的人之后,那么我们就知道了第二个房子是 21 岁的人,第五个房子是 24 岁的人......等等。

数组的缺点

祸兮福所倚,福兮祸所伏。数组的连续性既有优点又有缺点,优点上面已经说了,而缺点它对内存的要求比较高,必须要找到一块连续的内存才行。

数组的另一个缺点就是插入和删除的效率比较慢,假如我们在数组的非尾部插入或删除一个数据,那么就要移动之后的所有数据,这就会带来一定的性能开销,删除的过程如下图所示:

数组还有一个缺点,它的大小固定,不能动态拓展。

链表

链表是和数组互补的一种数据结构,它的定义如下:

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到 O(1) 的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要 O(n) 的时间,而顺序表相应的时间复杂度分别是 O(logn) 和 O(1)。

也就说链表是一个无需连续内存存储的数据结构,链表的元素有两个属性,一个是元素的值,另一个是指针,此指针标记了下一个元素的地址。

链表的数据结构,如下图所示:

链表添加的过程,如下图所示:

链表删除的过程,如下图所示:

链表分类

链表主要分为以下几类:

  • 单向链表

  • 双向链表

  • 循环链表

单向链表

单向链表中包含两个域,一个信息域和一个指针域。这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值,我们上面所展示的链表就是单向链表。

双向链表

双向链表也叫双链表,双向链表中不仅有指向后一个节点的指针,还有指向前一个节点的指针,这样可以从任何一个节点访问前一个节点,当然也可以访问后一个节点,以至整个链表。

双向链表的结构如下图所示:

循环链表

循环链表中第一个节点之前就是最后一个节点,反之亦然。循环链表的无边界使得在这样的链表上设计算法会比普通链表更加容易。

循环链表的结构如下图所示:

为什么会有单、双链表之分?

有人可能会问,既然已经有单向链表了,那为什么还要双向链表呢?双向链表有什么优势呢?

这个就要从链表的删除说起了,如果单向链表要删除元素的话,不但要找到删除的节点,还要找到删除节点的上一个节点(通常称之为前驱),因为需要变更上一个节点中 next 的指针,但又因为它是单向链表,所以在删除的节点中并没有存储上一个节点的相关信息,那么我们就需要再查询一遍链表以找到上一个节点,这样就带来了一定的性能问题,所以就有了双向链表。

链表优点

链表的优点大致可分为以下三个:

  1. 链表对内存的利用率比较高,无需连续的内存空间,即使有内存碎片,也不影响链表的创建;

  2. 链表的插入和删除的速度很快,无需像数组一样需要移动大量的元素;

  3. 链表大小不固定,可以很方便的进行动态扩展。

链表缺点

链表的主要缺点是不能随机查找,必须从第一个开始遍历,查找效率比较低,链表查询的时间复杂度是 O(n)。

性能评测

了解了数组和链表的基础知识之后,接下来我们正式进入性能评测环节。

在正式开始之前,我们先来明确一下测试目标,我们需要测试的点其实只有 6 个:

  • 头部/中间部分/尾部进行添加操作的性能测试;

  • 头部/中间部分/尾部开始查询的性能测试。

因为添加操作和删除操作在执行时间层面基本是一致的,比如数组添加需要移动后面的元素,删除也同样是移动后面的元素;而链表也是如此,添加和删除都是改变自身和相连节点的信息,因此我们就把添加和删除的测试合二为一,用添加操作来进行测试。

测试说明

  1. 在 Java 语言中,数组的代表为 ArrayList,而链表的代表为 LinkedList,因此我们就用这两个对象来进行测试;

  2. 本文我们将使用 Oracle 官方推荐 JMH 框架来进行测试,点击查看更多关于 JMH 的内容;

  3. 本文测试环境是 JDK 1.8、MacMini、Idea 2020.1。

1.头部添加性能测试

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.AverageTime) // 测试完成时间
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) // 预热次数和时间
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) // 测试次数和时间
@Fork(1) // fork 1 个线程
@State(Scope.Thread)
public class ArrayOptimizeTest {private static final int maxSize = 1000; // 测试循环次数private static final int operationSize = 100; // 操作次数private static ArrayList<Integer> arrayList;private static LinkedList<Integer> linkedList;public static void main(String[] args) throws RunnerException {// 启动基准测试Options opt = new OptionsBuilder().include(ArrayOptimizeTest.class.getSimpleName()) // 要导入的测试类.build();new Runner(opt).run(); // 执行测试}@Setuppublic void init() {// 启动执行事件arrayList = new ArrayList<Integer>();linkedList = new LinkedList<Integer>();for (int i = 0; i < maxSize; i++) {arrayList.add(i);linkedList.add(i);}}@Benchmarkpublic void addArrayByFirst(Blackhole blackhole) {for (int i = 0; i < +operationSize; i++) {arrayList.add(i, i);}// 为了避免 JIT 忽略未被使用的结果计算blackhole.consume(arrayList);}@Benchmarkpublic void addLinkedByFirst(Blackhole blackhole) {for (int i = 0; i < +operationSize; i++) {linkedList.add(i, i);}// 为了避免 JIT 忽略未被使用的结果计算blackhole.consume(linkedList);}
}

从以上代码可以看出,在测试之前,我们先将 ArrayListLinkedList 进行数据初始化,再从头部开始添加 100 个元素,执行结果如下:

从以上结果可以看出,LinkedList 的平均执行(完成)时间比 ArrayList 平均执行时间快了约 216 倍。

2.中间添加性能测试

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.AverageTime) // 测试完成时间
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) // 预热次数和时间
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) // 测试次数和时间
@Fork(1) // fork 1 个线程
@State(Scope.Thread)
public class ArrayOptimizeTest {private static final int maxSize = 1000; // 测试循环次数private static final int operationSize = 100; // 操作次数private static ArrayList<Integer> arrayList;private static LinkedList<Integer> linkedList;public static void main(String[] args) throws RunnerException {// 启动基准测试Options opt = new OptionsBuilder().include(ArrayOptimizeTest.class.getSimpleName()) // 要导入的测试类.build();new Runner(opt).run(); // 执行测试}@Setuppublic void init() {// 启动执行事件arrayList = new ArrayList<Integer>();linkedList = new LinkedList<Integer>();for (int i = 0; i < maxSize; i++) {arrayList.add(i);linkedList.add(i);}}@Benchmarkpublic void addArrayByMiddle(Blackhole blackhole) {int startCount = maxSize / 2; // 计算中间位置// 中间部分进行插入for (int i = startCount; i < (startCount + operationSize); i++) {arrayList.add(i, i);}// 为了避免 JIT 忽略未被使用的结果计算blackhole.consume(arrayList);}@Benchmarkpublic void addLinkedByMiddle(Blackhole blackhole) {int startCount = maxSize / 2; // 计算中间位置// 中间部分进行插入for (int i = startCount; i < (startCount + operationSize); i++) {linkedList.add(i, i);}// 为了避免 JIT 忽略未被使用的结果计算blackhole.consume(linkedList);}
}

从以上代码可以看出,在测试之前,我们先将 ArrayList 和 LinkedList 进行数据初始化,再从中间开始添加 100 个元素,执行结果如下:

从上述结果可以看出,LinkedList的平均执行时间比 ArrayList平均执行时间快了约 54 倍。

3.尾部添加性能测试

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.AverageTime) // 测试完成时间
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) // 预热次数和时间
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) // 测试次数和时间
@Fork(1) // fork 1 个线程
@State(Scope.Thread)
public class ArrayOptimizeTest {private static final int maxSize = 1000; // 测试循环次数private static final int operationSize = 100; // 操作次数private static ArrayList<Integer> arrayList;private static LinkedList<Integer> linkedList;public static void main(String[] args) throws RunnerException {// 启动基准测试Options opt = new OptionsBuilder().include(ArrayOptimizeTest.class.getSimpleName()) // 要导入的测试类.build();new Runner(opt).run(); // 执行测试}@Setuppublic void init() {// 启动执行事件arrayList = new ArrayList<Integer>();linkedList = new LinkedList<Integer>();for (int i = 0; i < maxSize; i++) {arrayList.add(i);linkedList.add(i);}}@Benchmarkpublic void addArrayByEnd(Blackhole blackhole) {int startCount = maxSize - 1 - operationSize;for (int i = startCount; i < (maxSize - 1); i++) {arrayList.add(i, i);}// 为了避免 JIT 忽略未被使用的结果计算blackhole.consume(arrayList);}@Benchmarkpublic void addLinkedByEnd(Blackhole blackhole) {int startCount = maxSize - 1 - operationSize;for (int i = startCount; i < (maxSize - 1); i++) {linkedList.add(i, i);}// 为了避免 JIT 忽略未被使用的结果计算blackhole.consume(linkedList);}
}

以上程序的执行结果为:

从上述结果可以看出,LinkedList 的平均执行时间比 ArrayList 平均执行时间快了约 32 倍。

4.头部查询性能评测

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.AverageTime) // 测试完成时间
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) // 预热次数和时间
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) // 测试次数和时间
@Fork(1) // fork 1 个线程
@State(Scope.Thread)
public class ArrayOptimizeTest {private static final int maxSize = 1000; // 测试循环次数private static final int operationSize = 100; // 操作次数private static ArrayList<Integer> arrayList;private static LinkedList<Integer> linkedList;public static void main(String[] args) throws RunnerException {// 启动基准测试Options opt = new OptionsBuilder().include(ArrayOptimizeTest.class.getSimpleName()) // 要导入的测试类.build();new Runner(opt).run(); // 执行测试}@Setuppublic void init() {// 启动执行事件arrayList = new ArrayList<Integer>();linkedList = new LinkedList<Integer>();for (int i = 0; i < maxSize; i++) {arrayList.add(i);linkedList.add(i);}}@Benchmarkpublic void findArrayByFirst() {for (int i = 0; i < operationSize; i++) {arrayList.get(i);}}@Benchmarkpublic void findLinkedyByFirst() { for (int i = 0; i < operationSize; i++) {linkedList.get(i);}}
}

以上程序的执行结果为:

从上述结果可以看出,从头部查询 100 个元素时 ArrayList 的平均执行时间比 LinkedList 平均执行时间快了约 1990 倍。

5.中间查询性能评测

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.AverageTime) // 测试完成时间
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) // 预热次数和时间
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) // 测试次数和时间
@Fork(1) // fork 1 个线程
@State(Scope.Thread)
public class ArrayOptimizeTest {private static final int maxSize = 1000; // 测试循环次数private static final int operationSize = 100; // 操作次数private static ArrayList<Integer> arrayList;private static LinkedList<Integer> linkedList;public static void main(String[] args) throws RunnerException {// 启动基准测试Options opt = new OptionsBuilder().include(ArrayOptimizeTest.class.getSimpleName()) // 要导入的测试类.build();new Runner(opt).run(); // 执行测试}@Setuppublic void init() {// 启动执行事件arrayList = new ArrayList<Integer>();linkedList = new LinkedList<Integer>();for (int i = 0; i < maxSize; i++) {arrayList.add(i);linkedList.add(i);}}@Benchmarkpublic void findArrayByMiddle() { int startCount = maxSize / 2;int endCount = startCount + operationSize;for (int i = startCount; i < endCount; i++) {arrayList.get(i);}}@Benchmarkpublic void findLinkedyByMiddle() { int startCount = maxSize / 2;int endCount = startCount + operationSize;for (int i = startCount; i < endCount; i++) {linkedList.get(i);}}
}

以上程序的执行结果为:

从上述结果可以看出,从中间查询 100 个元素时 ArrayList 的平均执行时间比 LinkedList 平均执行时间快了约 28089 倍,真是恐怖。

6.尾部查询性能评测

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.AverageTime) // 测试完成时间
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) // 预热次数和时间
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) // 测试次数和时间
@Fork(1) // fork 1 个线程
@State(Scope.Thread)
public class ArrayOptimizeTest {private static final int maxSize = 1000; // 测试循环次数private static final int operationSize = 100; // 操作次数private static ArrayList<Integer> arrayList;private static LinkedList<Integer> linkedList;public static void main(String[] args) throws RunnerException {// 启动基准测试Options opt = new OptionsBuilder().include(ArrayOptimizeTest.class.getSimpleName()) // 要导入的测试类.build();new Runner(opt).run(); // 执行测试}@Setuppublic void init() {// 启动执行事件arrayList = new ArrayList<Integer>();linkedList = new LinkedList<Integer>();for (int i = 0; i < maxSize; i++) {arrayList.add(i);linkedList.add(i);}}@Benchmarkpublic void findArrayByEnd() {for (int i = (maxSize - operationSize); i < maxSize; i++) {arrayList.get(i);}}@Benchmarkpublic void findLinkedyByEnd() { for (int i = (maxSize - operationSize); i < maxSize; i++) {linkedList.get(i);}}
}

以上程序的执行结果为:

从上述结果可以看出,从尾部查询 100 个元素时 ArrayList 的平均执行时间比 LinkedList 平均执行成时间快了约 1839 倍。

7.扩展添加测试

接下来我们再来测试一下,正常情况下我们从头开始添加数组和链表的性能对比,测试代码如下:

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.AverageTime) // 测试完成时间
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) // 预热次数和时间
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) // 测试次数和时间
@Fork(1) // fork 1 个线程
@State(Scope.Thread)
public class ArrayOptimizeTest {private static final int maxSize = 1000; // 测试循环次数private static ArrayList<Integer> arrayList;private static LinkedList<Integer> linkedList;public static void main(String[] args) throws RunnerException {// 启动基准测试Options opt = new OptionsBuilder().include(ArrayOptimizeTest.class.getSimpleName()) // 要导入的测试类.build();new Runner(opt).run(); // 执行测试}@Benchmarkpublic void addArray(Blackhole blackhole) { // 中间删数组表arrayList = new ArrayList<Integer>();for (int i = 0; i < maxSize; i++) {arrayList.add(i);}// 为了避免 JIT 忽略未被使用的结果计算blackhole.consume(arrayList);}@Benchmarkpublic void addLinked(Blackhole blackhole) { // 中间删除链表linkedList = new LinkedList<Integer>();for (int i = 0; i < maxSize; i++) {linkedList.add(i);}// 为了避免 JIT 忽略未被使用的结果计算blackhole.consume(linkedList);}
}

以上程序的执行结果为:

接下来,我们将添加的次数调至 1w,测试结果如下:

最后,我们再将添加次数调至 10w,测试结果如下:

从以上结果可以看出在正常情况下,从头部依次开始添加元素时,他们性能差别不大。

总结

本文我们介绍了数组的概念以及它的优缺点,同时还介绍了单向链表、双向链表及循环链表的概念以及链表的优缺点。我们在最后的评测中可以看出,当我们正常从头部依次添加元素时,链表和数组的性能差不不大。但当数据初始化完成之后,我们再进行插入操作时,尤其是从头部插入时,因为数组要移动之后的所有元素,因此性能要比链表低很多;但在查询时性能刚好相反,因为链表要遍历查询,并且 LinkedList 是双向链表,所以在中间查询时性能要比数组查询慢了上万倍(查询 100 个元素),而两头查询(首部和尾部)时,链表也比数组慢了将近 1000 多倍(查询 100 个元素),因此在查询比较多的场景中,我们要尽量使用数组,而在添加和删除操作比较多时,我们应该使用链表结构

数组和链表的操作时间复杂度,如下表所示:


数组链表
查询O(1)O(n)
插入O(n)O(1)
删除O(n)O(1)
最后的话原创不易,用心写好每篇文章,若能看出来,请给我一个「在看」鼓励吧。往期推荐

轻松学算法的秘密!可视化算法网站汇总!(附动图)

50种Java编程技巧,越早知道越好!(建议收藏)

关注下方二维码,每一天都有干货!

点亮“在看”,助我写出更多好文!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/546070.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win7安装python

2019独角兽企业重金招聘Python工程师标准>>> 官网下载 python 安装包&#xff0c;一个 .msi 文件&#xff0c;双击安装 右键[计算机]-属性-高级系统设置-环境变量&#xff0c;在[系统变量]中找到 Path 变量&#xff0c;双击&#xff0c;在值后面添加 python 的安装路…

漫画:Java如何实现热更新?

Arthas&#xff08;阿尔萨斯&#xff09;是 Alibaba 开源的一款 Java 诊断工具&#xff0c;使用它我们可以监控和排查 Java 程序&#xff0c;然而它还提供了非常实用的 Java 热更新功能。所谓的 Java 热更新是指在不重启项目的情况下实现代码的更新与替换。使用它可以实现不停机…

自动化运维工具Saltstack详细介绍

Saltstack是一个新的基础设施管理工具。目前处于快速发展阶段&#xff0c;可以看做是pssh弱化的Puppet的组合。间接的反映出了saltstack的两大功能&#xff1a;远程执行和配置管理。Saltstack使用Python开发&#xff0c;是一个非常简单易用和轻量级的管理工具。由Master和Minio…

为什么建议你使用枚举?

枚举是 JDK 1.5 新增的数据类型&#xff0c;使用枚举我们可以很好的描述一些特定的业务场景&#xff0c;比如一年中的春、夏、秋、冬&#xff0c;还有每周的周一到周天&#xff0c;还有各种颜色&#xff0c;以及可以用它来描述一些状态信息&#xff0c;比如错误码等。枚举类型不…

数据结构树二叉树计算节点_查找二叉树中叶节点的数量 数据结构

数据结构树二叉树计算节点Algorithm: 算法&#xff1a; One of the popular traversal techniques to solve this kind of problems is level order tree traversal (Read: Level Order Traversal on a Binary Tree) where we use the concept of BFS. 解决此类问题的一种流行…

重磅!阿里推出国产开源JDK!

简介Alibaba Dragonwell 是一款免费的, 生产就绪型Open JDK 发行版&#xff0c;提供长期支持&#xff0c;包括性能增强和安全修复。阿里巴巴拥有最丰富的Java应用场景&#xff0c;覆盖电商&#xff0c;金融&#xff0c;物流等众多领域&#xff0c;世界上最大的Java用户之一。Al…

安装TPCC-MySQL报错

2019独角兽企业重金招聘Python工程师标准>>> 安装TPCC-MySQL做压力测试&#xff0c;由于TPCC-MySQL是bzr工具进行版本控制的&#xff0c;所以要先安装bzr [rootmha_backup /root] #rpm -Uvh http://dl.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.r…

自由职业的前半年,我是如何度过的?

生活中所受的苦&#xff0c;终会以一种形式回归。我是一个后知后觉的人&#xff0c;从 2009 年毕业到现在&#xff0c;已经有 11 年的光景了&#xff0c;参加工作的前几年我从没想过要快速的提升自己的技能&#xff0c;对待工作也没有全力以赴&#xff0c;这样的迷茫和随大流的…

Eucalyptus常用查询命令

前言&#xff1a; Elastic Utility Computing Architecture for Linking Your Programs To Useful Systems &#xff08;Eucalyptus&#xff09; 是一种开源的软件基础结构&#xff0c;用来通过计算集群或工作站群实现弹性的、实用的云计算。它最初是美国加利福尼亚大学 Santa …

调整灰度图像的大小,而无需在Python中使用任何内置函数

In this program, we will be using two functions of OpenCV-python (cv2) module. Lets see their syntax and descriptions first. 在此程序中&#xff0c;我们将使用OpenCV-python(cv2)模块的两个功能。 首先让我们看看它们的语法和说明。 1) imread():It takes an absolu…

漫画:对象是如何被找到的?句柄 OR 直接指针?

小贴士&#xff1a;想要使用并定位 Java 对象&#xff0c;就要用到 Java 虚拟机栈&#xff08;Java Virtual Machine Stack&#xff09;&#xff0c;它描述的是 Java 方法执行的线程内存模型&#xff1a;每个方法被执行的时候&#xff0c;Java 虚拟机都会同步创建一个栈帧&…

IDEA 不为人知的 5 个骚技巧!真香!

工欲善其事&#xff0c;必先利其器&#xff0c;磊哥最近发现了几个特别棒的 IDEA“骚”技巧&#xff0c;已经迫不及待的想要分享给你了&#xff0c;快上车...1.快速补全行末分号使用快捷键 Shfit Ctrl Enter 轻松实现。2.自带的 HTTP 请求工具IDEA 自带了 HTTP 的测试工具&am…

漫画:Integer 竟然有 4 种比较方法?

代码测试public class IntegerTest {public static void main(String[] args) {Integer i1 127;Integer i2 127;System.out.println(i1 i2);Integer i3 128;Integer i4 128;System.out.println(i3 i4);} }以上代码的执行结果为&#xff1a;truefalse首先&#xff0c;当我…

6种快速统计代码执行时间的方法,真香!(史上最全)

我们在日常开发中经常需要测试一些代码的执行时间&#xff0c;但又不想使用向 JMH&#xff08;Java Microbenchmark Harness&#xff0c;Java 微基准测试套件&#xff09;这么重的测试框架&#xff0c;所以本文就汇总了一些 Java 中比较常用的执行时间统计方法&#xff0c;总共…

连夜整理了几个开源项目,毕设/练手/私活一条龙!

一直以来&#xff0c;总有小伙伴问说&#xff1a;诶&#xff0c;有没有什么好的项目推荐啊&#xff0c;想参考使用。一般用途无非如下几种情况&#xff1a;自学练手&#xff1a;从书本和博客的理论学习&#xff0c;过渡到实践练手吸收项目经验&#xff0c;找工作写简历时能参考…

MPI编程简单介绍

第三章 MPI编程 3.1 MPI简单介绍 多线程是一种便捷的模型&#xff0c;当中每一个线程都能够訪问其他线程的存储空间。因此&#xff0c;这样的模型仅仅能在共享存储系统之间移植。一般来讲&#xff0c;并行机不一定在各处理器之间共享存储&#xff0c;当面向非共享存储系统开发…

最简单的6种防止数据重复提交的方法!(干货)

有位朋友&#xff0c;某天突然问磊哥&#xff1a;在 Java 中&#xff0c;防止重复提交最简单的方案是什么&#xff1f;这句话中包含了两个关键信息&#xff0c;第一&#xff1a;防止重复提交&#xff1b;第二&#xff1a;最简单。于是磊哥问他&#xff0c;是单机环境还是分布式…

漫画:如何证明sleep不释放锁,而wait释放锁?

wait 加锁示例public class WaitDemo {private static Object locker new Object();public static void main(String[] args) throws InterruptedException {WaitDemo waitDemo new WaitDemo();// 启动新线程&#xff0c;防止主线程被休眠new Thread(() -> {try {waitDemo…

设计模式 之 建造者

建造者模式&#xff08;Builder Pattern&#xff09; 一听这个名字&#xff0c;你可能就会猜到一二分了。建造者简单理解就是造东西&#xff0c;仅仅只是建造者模式建造的不是一个简单的东西&#xff0c;是一个比較复杂的东西。就好像盖房子&#xff0c;须要打地基、砌墙、灌…

支付宝上市,让我损失了2000万(盘点这些年错过的机会)

选择大于努力&#xff01;这句话在之前&#xff0c;我只是用排除法来解释它&#xff08;如果你的选择是错的&#xff0c;那么走的越快就离目标越远&#xff09;&#xff0c;而如今几次亲身的经历&#xff0c;却给了我不同的答案...近几天支付宝上市的事儿&#xff0c;传的沸沸扬…