Java优先队列(PriorityQueue)介绍

队列(Queue)这种数据结构,是”先来先服务”(FIFO)的。 但是有的时候,我们需要对“优先级”高的对象先处理。或者说,我们想在队列中按照我们喜欢的样子排序。

Java 1.5,开始引入了优先队列(PriorityQueue)

简单来说,要使用这个队列,那么放入队列的对象要实现Comparable接口。之后,队列在添加元素的时候,就会根据这个方法,放入合适的位置。取出的时候,会弹出排在最前面的元素。

下面,我们通过一个例子体会一下优先队列的作用和用法。


这个练习题来自HackkerRank:Java Priority Queue

题目要求

学生有token,成绩,名字。每次输入一个命令,如果是“ENTER”,就添加新的学生进来,按照成绩排序放入。如果成绩相同,按照名字字母序放入。如果名字也相同,就按照token放。 如果命令是“SERVED”,就弹出最前面的同学。最后,打印剩下的队列,如果为空,打印“EMPTY”。

输入示例

输出示例

我的代码:

通过这个例子,可以很好地理解优先队列了。

参考资料

Java优先队列(PriorityQueue)示例

 

详解 Python 的 “==” 和 “is”

Python中比较两个对象是否相等,一共有两种方法,简单来说,它们的区别如下:

  1. is是比较两个引用是否指向了同一个对象(引用比较)。
  2. ==是比较两个对象是否相等。

实现原理

is比较的是两者是否是同一个对象,所以比较的是内存地址(id是否相同)。

Python文档3.1 对象、值和类型中是这样说的:

每个变量都有标识、类型和值。对象一旦创建,它的标识绝不会变;你可以把标识理解为对象在内存中的地址。is运算符比较两个对象的标识;id()返回对象标识的证书标识。

对象ID真正的意义在不同的实现中也不同,在CPython中,id()返回的对象的内存地址,在其他解释器中可能是别的意义。但重要的是,它一定能表示唯一的对象并且在对象的生命周期内不变,不同对象的标识一定是不一样的。

==是值比较。不可变对象,例如int,str,它会直接进行值比较。对于Python已知的对象,会调用他们的__eq__函数来比较。(其实已知的对象应该也是通过内置的__eq__函数来比较的)。对于自定义的对象,如果实现了__eq__函数,就会使用它比较,如果没有实现,效果和==是一样的。

对象缓存机制

Python会对比较小的对象缓存,下次用到比较小的对象时,会去缓存区查找,如果找到,不会再开辟新的内存,而是继续把小对象的地址赋给新的值。例子:

通过计算得到的赋值,不会使用缓存区。从第一个代码示例中可以看出。

对于字符串,你可以通过使用intern函数强制使用缓存区。

总结

这一段总结引用自《Fluent Python》,我觉得写的非常好:

is运算符比==快,因为它不能被重载,所以Python不必寻找并调用特殊方法,而是直接比较两个证书id。而a == b 则是一个语法糖,等同于a.__eq__(b)。继承自object的__eq__方法比较两个对象的id,结果与is一样。但是多数内置类型使用更有意义的方法覆盖了__eq__方法,会考虑对象属性的值。相等性测试可能涉及大量处理工作,例如,比较大型集合或嵌套层级深的结构时。

参考

  1. Is there a difference between `==` and `is` in Python?
  2. python源码学习(八)——string对象的intern机制
  3. 比较python类的两个instance(对象) 是否相等
  4. 《Fluent Python》8.2 标志、相等性和别名
 

Apache2 AH00558 警告解决办法

Apache2 在Ubuntu下有下面的警告:

如果是在服务器端,那么127.0.0.1就是你的服务器内网IP。

查了一下资料,在/etc/apache2/httpd.conf文件中添加一行ServerName localhost就可以解决,但是我在Ubuntu下并没有找到httpd.conf配置文件。


解决方法:在Ubuntu下,相应的文件应该是apache2配置目录(默认是/etc/apache2/)下面的apache2.conf。所以搞定这个警告的具体步骤如下:

参考:https://aslamnajeebdeen.com/how-to-fix-apache-could-not-reliably-determine-the-servers-fully-qualified-domain-name-using-127011-for-servername-error-on-ubuntu

 

Mac pyenv安装失败的解决办法

写了很久的Python2,今天被Python3 *等特性吸引了,忍不住想试一下。

在MAC OS X上Python的多版本共存,我们可以使用pyenv来解决,配合virtualenv,可以轻松搭建多个虚拟环境。

但是安装的时候,遇到了两个问题。

在官网的issues#429发现,用下面的方式解决。

然后又遇到了下面的问题:

然后又查到了issue#451,应该使用下面的命令来安装。

然后,就安装成功了。


如果需要使用虚拟环境,可以使用下面的命令安装pyenv-virtualenv插件,然后新建虚拟环境。

以这样的方式新建的虚拟环境,位置在~/.pyenv/versions如果使用pycharm的话,可以从这个路径导入。

 

Python对Json的解析

什么是Json

Json是一种常用的数据交换结构,由于轻量、易于阅读和编写等特点,在网络方面应用很广。

它的格式一般是这样的:

对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。

例如下面这样:

它的值可以是双引号括起来的字符串(string)、数值(number)、truefalsenull、对象(object)或者数组(array)。这些结构可以嵌套。

使用Python编码和解析Json

Python内置了json包来帮助我们完成对json的操作。

将Python的字典结构导出到json使用json.dumps(),将json读成Python的字典结构,使用json.loads()

如果不是针对string操作而是对文件操作,分别使用json.load()函数和json.dump()函数。

默认的类型对应如下:

JSON Python
object dict
array list
string unicode
number (int) int, long
number (real) float
true True
false False
null None

其他数据类型与Json之间的编码和解码

一般来说,Python对json的解析是listdict之间的操作,如果需要其他类型与json之间转换,就需要object_hook参数。先定义一个类,将类的字典初始化成json的key-value键值对。这样,json的参数就变成了类的属性。

还可以通过指定“函数”来进行转换。

用函数来指定序列化的方法,即将对象的“属性-值”对变成字典对,函数返回一个字典,然后json.dumps会格式化这个字典。

如果是通过函数将json变成对象,首先获得类名,然后通过__new__来创建一个对象(不调用初始化函数),然后将json字典的各个属性赋给对象。

使用方法如下:

参考