HashMap的排序

前言 HashMap 在 Java 里面是一种非常实用的工具,他清楚明白的反映了**“键-值”**之间的关系,HashMap 本身是无序的,但是 HashMap 的排序却是一个比较常见的问题,这里针对 HashMap 的两种排序方式做了笔记。 import java.util.*; class Main { public static void main(String[] args) { Map<Integer, String> map1 = new HashMap<>(); map1.put(3, "三"); map1.put(6, "六"); map1.put(1, "一"); Map<String, Integer> map2 = new HashMap<>(); map2.put("三", 3); map2.put("一", 1); map2.put("六", 6); sortByKey(map1); sortByValue(map2); } // 按照键排序 static void sortByKey(Map map) { Object[] objects = map.keySet().toArray(); Arrays.sort(objects); for (int i = 0; i < objects.length; i++) { System.out.println("键:" + objects[i] + " 值:" + map.get(objects[i])); } } // 按照值排序 static void sortByValue(Map map) { List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(map.entrySet()); Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o1.getValue().compareTo(o2.getValue()); } }); for (Map.Entry<String, Integer> mapping : list) { System.out.println("键:" + mapping.getKey() + " 值:" + mapping.getValue()); } } }

plainify

IP 地址怎么定位?

我们经常可以在影视作品中见到某某组织通过对某个人的 IP 地址进行监控,定位其位置,甚至精确到某栋大楼的某一层,如此可怕的场景在现实生活中真的有可能会发生吗? 先来说结果,仅通过 IP 地址最精确能够达到街道级别。而且在不通过运营商的用户数据库查询情况下,定位到家庭住址和单元楼的情况难度很高。 ISP 在《互联网是如何工作的》一文中,我们介绍道,IP 地址是类似于现实世界中的地址这样的东西,通过 IP 地址,我们就可以在网络上定位到一台计算机,在现实世界中,IP 地址是由一个叫互联网服务提供商,即 ISP 提供的。 回想一下我们上网的过程: 去运营商(移动、电信、联通)办理宽带业务 -> 业务员上门拉线 -> 电脑连接宽带 -> 访问互联网 在这一过程中,三大运营商就是我们能接触到的 ISP 的,ISP 可以从互联网管理机构申请到很多 IP 地址,然后一些机构和个人从某个 ISP 获取 IP 地址的使用权,并可通过该 ISP 连接到互联网。 那么 ISP 又是如何标记 IP 地址的地理位置的呢? 我们先来说说 ISP 的三层结构。 三层 ISP 结构分为主干 ISP,地区 ISP,本地 ISP。本地 ISP 给用户提供最直接的服务,本地 ISP 可以连接到地区 ISP,也可以连接到主干 ISP。从原理上讲。只要每一个本地 ISP 都安装了路由器连接到某个地区 ISP,而每一个地区 ISP 也有路由器连接到主干 ISP,那么在这些相互连接的 ISP 的共同作用下,就可以完成互联网中的所有的分组转发任务。 这里我们通过计算机网络教材中的一张图来理解三层结构,如图 1 所示 👇 也就是说,当你向好友发了一条微信,这条微信首先会从你所在公司/学校的内网上发到当地的服务器,再从当地服务器发送到地区服务器,之后从地区服务器通过移动/联通/电信的服务器向你好友所在地的地区服务器转发,再通过本地服务器最终转发到好友所在公司/学校的内网。 ...

ISE头条号海报生成器

完整源码可在公众号:「01二进制」后台回复:「海报生成器」获取 最近自闭了一段时间,仔细思考一番后还是决定要把自己心中所想坚持下去。今天来分享一个日常生活中经常见到,但是制作起来又可能会一时没有思路的东西,主要功能就是生成带二维码的卡片或者海报。 之前莫名其妙的被导师安排负责管理实验室的头条号,任务不难,就是接收实验室学长学姐翻译转述的论文,然后再发布到今日头条的头条号上,最后再生成如下所示的宣传图即可: 当时觉得,不就是发发文章,然后再用ps做个图这么简单吗。可接手之后才发现我毕竟图样图森破啊,从去年11月我开始发文章到今天,期间从未有一天断过,但是这头条号的编辑器也从未更新过,一个这么大的自媒体企业,文章的编辑器竟然烂的跟坨💩一样,不支持外部图片,不支持markdown,不支持数学公式,不支持多级标题。(别跟我说什么可以把markdown转成html然后再复制进头条号的编辑器里面,样式都变成鬼了) 扯远了扯远了,回到正题。之前这么多天实现上述需要的主要流程如下: (采取各种方式优化排版)把文章发布到(不支持各种常用功能的)头条号上 文章发布后,获取其文章链接,并到草料二维码生成器网站,上传实验室logo后生成二维码下载至本地 利用PhotoShop将封面图、文章标题和文章二维码合成在一起后发给老师。 在经历了100天上述这样重复的操作之后,我厌烦了。难道就没有一个工具可以让我只输入文章链接和标题就自动生成海报的吗? 苦苦寻觅半天无果,也罢,有条件要上,没条件创造条件也要上。没有现成的轮子,那就只能自己打造一个了,Python无疑是开发这个小工具的首选。 一般用于推广的海报或卡片样式都差不多,需要改变的主要就是二维码,所以只需要准备好海报的背景图,然后根据用户提供的二维码,将其贴在海报指定的位置上即可。 此次实验的项目结构如下: assets文件夹中包含一些资源文件,例如msyhl.ttc(字体文件)、template.jpg(背景模版图片)。output是生成的海报存放的路径 生成带logo的二维码 本次生成二维码依赖于 PIL 模块和 qrcode 库,官方地址为:https://pypi.org/project/qrcode/5.1/,这里不解释用法,感兴趣的自己去官方文档下了解。这里就直接上代码了,具体代码的用意详见注释: # 生成一个带logo的二维码 def generateQRCode(url): # 初始化 qr = qrcode.QRCode( version=5, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=8) # 添加内容 qr.add_data(url) qr.make(fit=True) img = qr.make_image() img = img.convert("RGBA") # 读取logo icon = Image.open("assets/logo.jpg") # 设置logo img_w, img_h = img.size factor = 4 size_w = int(img_w / factor) size_h = int(img_h / factor) icon_w, icon_h = icon.size if icon_w > size_w: icon_w = size_w if icon_h > size_h: icon_h = size_h icon = icon.resize((icon_w, icon_h), Image.ANTIALIAS) # 将logo并入原二维码中 w = int((img_w - icon_w)/2) h = int((img_h - icon_h)/2) icon = icon.convert("RGBA") img.paste(icon, (w, h), icon) rgb_im = img.convert('RGB') # 保存到指定路径下 today = datetime.date.today() folder_path = 'output/'+str(today) mkdir(folder_path) rgb_im.save(folder_path+'/qr.jpg') 生成海报 我们先来梳理下,想要生成一张满足我们需求的海报需要哪些元素: ...

Java 中链表与数组间的相互转换

自定义链表 ListNode 类 public class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } 将链表转换成数组 //将链表转换成数组 public class Test1 { public static void main(String[] args) { Test1 test1 = new Test1(); int[] a = {1, 9, 9, 9, 9, 9, 9, 9, 9, 9}; ListNode l1 = test1.arrayToListNode(a); test1.printListNode(l1); } //数组转换成链表 public ListNode arrayToListNode(int[] s) { ListNode root = new ListNode(s[0]);//生成链表的根节点,并将数组的第一个元素的值赋给链表的根节点 ListNode other = root;//生成另一个节点,并让other指向root节点,other在此作为一个临时变量,相当于指针 for (int i = 1; i < s.length; i++) {//由于已给root赋值,所以i从1开始 ListNode temp = new ListNode(s[i]);//每循环一次生成一个新的节点,并给当前节点赋值 other.next = temp;//将other的下一个节点指向生成的新的节点 other = temp;//将other指向最后一个节点(other的下一个节点) other=other.getNext(); } return root; } /** * 遍历一个链表 */ public void printListNode(ListNode l) { while (l != null) { System.out.print(l.val + " "); l = l.next; } } } ...

257 words 2 min

Java 并查集的实现

概念 其实并查集顾名思义就是有“合并集合”和“查找集合中的元素”两种操作的关于数据结构的一种算法。 用途 维护无向图的连通性。支持判断两个点是否在同一连通块内。 判断增加一条边是否会产生环:用在求解最小生成树的Kruskal算法里。 操作 并查集主要就三个操作:初始化、合并、查找 初始化 一般来说,并查集的初始化用数组即可,例如数组Tree[i],i表示某节点,tree[i]表示当前节点的根节点 查找函数 这里的查找和java集合类List中的查找函数get()并不一样,他的作用是查找该节点的根节点,如果集合的parent等于集合的编号(即还没有被合并或者没有同类),那么自然返回自身编号。如果不同那么就可以调用递归函数。 代码如下 // 并查集查找根节点 static int findRoot(int x, int[] arr) { // 如果集合i的父亲是自己,说明自己就是源头,返回自己的标号 if (arr[x] == -1) return x; else // 否则查找集合i的父亲的源头 return findRoot(arr[x], arr); } 若需要在查找过程中添加路径压缩的优化,我们修改上面这个函数为: // 并查集查找根节点(优化算法,本质是将路径压缩了) static int findRootUseful(int x, int[] arr) { int res = 0; if (arr[x] == -1) return x; else { res = findRoot(arr[x], arr); arr[x] = res; // 将当前结点的双亲结点设置为查找返回的根结点编号 return res; } } ...

Java中的进制转换

近期刷题时遇到了进制转换,在这整理一波 方法: 十进制转其他进制 Integer.toHexString(int i);//转成16进制 Integer.toBinaryString(int i);//转成二进制 Integer.toOctalString(int i);//转成8进制 Integer.toString(int i, int radix);//转成任意进制,radix不在【2,36】区间内radix=10 Long.toHexString(long i);//转成16进制 Long.toBinaryString(long i);//转成二进制 Long.toOctalString(long i);//转成8进制 Long.toString(long i, int radix);//转成任意进制,radix不在【2,36】区间内radix=10 其他进制转十进制 Integer.valueOf(String s, int radix); 返回值类型为Integer,radix不在【2,36】区间内,抛出NumberFormatException异常 parseInt(String s, int radix); 返回值类型为:int,radix不在【2,36】区间内,抛出NumberFormatException异常 各进制间的转换 Integer.toString(parseInt(String s, int srcRadix), int destRadix);

Java中计算两个日期间隔多少天

String dbtime1 = "2017-02-23"; //第二个日期 String dbtime2 = "2017-02-22"; //第一个日期 //算两个日期间隔多少天 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date date1 = format.parse(dbtime1); Date date2 = format.parse(dbtime2); int a = (int) ((date1.getTime() - date2.getTime()) / (1000*3600*24)); 直接通过计算两个日期的毫秒数,他们的差除以一天的毫秒数,即可得到想要的两个日期相差的天数。

34 words 1 min

mac下利用pyenv管理多个版本的python

前言 经常遇到这样的情况: 系统自带的Python是2.x,自己需要Python 3.x; 某些机器学习的框架(如PaddlePaddle/Tensorflow)需要的版本是python3.5,但是你的系统支持的python版本较高,且无法删除(因为某些软件会和python产生依赖) 此时需要在系统中安装多个Python,但又不能影响系统自带的Python,即需要实现Python的多版本共存。pyenv就是这样一个Python版本管理器。 ...

pyenv下使用python matplotlib模块的问题解决

错误信息 先来描述一下我遇到的问题,在进行matplotlib学习时,plot.show()总是无法成功运行,总是会报一个错: RuntimeError: Python is not installed as a framework. The Mac OS X backend will not be able to function correctly if Python is not installed as a framework. See the Python documentation for more information on installing Python as a framework on Mac OS X. Please either reinstall Python as a framework, or try one of the other backends. If you are using (Ana)Conda please install python.app and replace the use of ‘python’ with ‘pythonw’. See ‘Working with Matplotlib on OSX’ in the Matplotlib FAQ for more information. 其实意思很简单,就是我用的python并不是一个作为系统框架存在的,因为我为了方便管理python的版本,选择了pyenv这个管理工具,是一个独立出来的python环境。 ...

Python 管理哪家强?

之前介绍过《利用pyenv管理多个版本的python》,pyenv 是一个非常好用的 Python 版本管理工具,利用它我们可以在同一台电脑上安装多个版本的 Python ,这个过程非常简单。Mac系统的电脑一行命令就可以安装了: brew install pyenv pyenv 的安装和使用详见开篇提到的文章,这里不再赘述。 今天主要是想介绍另一个非常好用的 Python 工具——“Pipenv” Pipenv是什么? Pipenv is a tool that aims to bring the best of all packaging worlds (bundler, composer, npm, cargo, yarn, etc.) to the Python world. Windows is a first-class citizen, in our world. It automatically creates and manages a virtualenv for your projects, as well as adds/removes packages from your Pipfile as you install/uninstall packages. It also generates the ever-important Pipfile.lock, which is used to produce deterministic builds. ...