0%

哈希表(Hash Table)

哈希表的一般原理

哈希表的参照物是数组或者链表,在后者中取值或者查找总是避免不了一个循环操作,造成O(n)的开销,通过构建哈希表可以将此类操作开销降低到O(1)。

典型哈希表的流程如下

“HashTable”的图片搜索结果

这是一个电话号码簿,以人名作为键值(key),将 key 值代入哈希函数得到 hash 值,通过 hash 值得到数组下标,通过下标可以在电话号码数组里直接得到号码。

为了这一高效过程付出的代价是

  • 哈希函数的开销,该函数必须控制计算量
  • 如果存储 hash 值,要付出额外的空间开销,例如 java 为每一个类提供 hash 属性
  • hash 表构建开销为O(n),不过这一开销是一次性的,能够被此后表的操作所摊还;不过频繁的重建表还是要避免的

此外哈希表还有两个问题

1.哈希函数的构造,主要是使得输出结果区间分配均匀,避免带来过多的哈希冲突

2.哈希冲突。上图红色部分就显示了一个 hash 冲突,两个不同的人名通过 哈希函数得到相同的 hash 值,导致他们有得到同一个电话号码的风险。

哈希冲突的两种解决方法

不管选怎样的哈希函数,Hash 冲突都是不可避免的。为了解决这一问题,建立哈希表时可以采用两种方法

  • 分离链接法

img

buckets 中存放的元素都是链表,计算得到下标后获得此位置上的链表,将数据写入链表即可。发生 hash 冲突的数据一并都写入链表,查找时先在 buckets 数组中找链表,这一步开销是O(1),而后在链表里找数据。

这种方法需要遍历链表,这一部分开销与链表平均长度有关,可以等价于装填因子有关。一般而言,装填因子可以达到 1.

  • 开放定址法

img

这种方法不在使用链表,发生冲突后在冲突位置往后寻找一个空位安放数据。寻找安置空位的方法有

  • 线性探测 逐个探测表,直到查找到一个空单元,把散列地址存放在该空单元。
  • 平方探测 相对线性探测,相当于探测间隔 i*i 个单元的位置是否为空。
  • 伪随机探测

考虑将 {89,18,49,58,69} 插入到一个散列表,散列函数是简单的除10求余数,冲突处理采用开放定址线性检测,其过程如下

散列地址 空表 插入89 插入18 插入49 插入58 插入69
0 49 49 49
1 58 58
2 69
3
4
5
6
7
8 18 18 18 18
9 89 89 89 89 89

如果采用平方定址法

散列地址 空表 插入89 插入18 插入49 插入58 插入69
0 49 49 49
1
2 58 58
3 69
4
5
6
7
8 18 18 18 18
9 89 89 89 89 89

插入 58 发生冲突,第一次寻址是偏移 1 位,但此位被占据,第二次寻址是 4 位,即所处位置。

开放定址的问题是随着表中元素的增多,插入寻址会变得越来越困难。当装填因子超过一定值后,插入新元素将变的不可能,这时就需要重新构造一个容积更大的哈希表,这个操作叫做再散列。使用分离链接法解决哈希冲突是没有这个问题的。

再散列后新表的大小一般是旧表的两倍。

对于开放定址法,荷载因子是特别重要因素。超过0.8,查表时的缓存不命中(cache missing)按照指数曲线上升。例如 Java 系统库限制荷载因子为0.75,超过此值将发生再散列。

哈希表的实现

Python 中的字典 dict ,Java 中的 HashMap 都采用哈希表实现,以提高效率。不同的是前者采用开放定址法,后者采用分离链接法。

Python 的字典

字典的使用

1
2
teams = {"seriaA":"inter", "Liga":"Barça", "Premier":"Liverpool"}
teams["seriaA"] // inter

python的函数函数为 hash()

1
hash("seriaA") // -6110547274228262006

python 用一个数组来存储键/值对,其中键为索引值。索引的计算如下

1
hash("seriaA") & (len-1) // len 是数组长度, & 运算等价于求余

probing sequence

Java 中的 HashMap

HashMap 的使用

1
2
3
Map<String, String> map = new HashMap<>();
map.put("SeriaA", "inter");
String team = map.get("SeriaA");

键值对存放的数组是

1
HashMap.Node<K, V>[] table;

其中 Node 定义如下,是典型的链表,说明 HashMap 采用的是分离链接法

1
2
3
4
5
6
static class Node<K, V> implements Entry<K, V> {    
int hash;
K key;
V value;
HashMap.Node<K, V> next;
}

执行 put 操作的流程

1.首先利用下式计算出 key 对应的下标 i ,如果table中此位置无元素存在,那么创建 Node 节点并写入键值对即可

1
hash(key) & (table.length-1)

2.如果 table[i] 上已经有元素存在,遍历链表比对 hash值和key值,如果发现均相同的元素,则认为找到了元素,此时 put 的操作实际是 “修改已存在的元素“;如果没有找到,则此时 put 的操作实际是 “添加新元素。”

1
Node.hash == hash && (Node.key == key || Node.key.equals(key))

上述条件说的是只要两个元素的 hash值相同至少满足equal 条件,即在 HashMap 中视为同一个元素。

ArrayMap

ArrayMap 与 HashMap 相比,是实现字典的另一种思路,它已经不采用哈希表来实现。它主要有两个数组

1
2
int[] mHashes;		//存放 hash 值的数组
Object[] mArray; //存放 key-vaule 的数组

它的 put 操作流程是

1.先计算hash值和下标

1
2
hash = key.hashCode();
int index = binarySearchHashes(mHashes, N, hash);

2.写入数据

1
2
3
mHashes[index] = hash;        // 下标是hash数组中的下标
mArray[index<<1] = key; // 存放到键值对数组中要先换算下标
mArray[(index<<1)+1] = value;

可见键值对在数组中完全是并排存放的,而由hash值到下标的计算也不再使用哈希函数,而是将其按序排列使用二分查找,这步的开销是O(log(n)),比 HashMap 要大,但比数组要小。可以想见,在处理海量数据,例如城市居民通讯录时是不能采用这种结构的。

SparseArray

SparseArray 的使用如下

1
2
3
SparseArray<String> array = new SparseArray<>();
array.put(1, "inter");
String team = array.get(1);

主要存储结构如下,它的 key 和 value 是分开存放的,只不过 key 是特殊的 int 类型,设计这种结构是为了避免 Integer 类型的装箱和解装箱开销。

1
2
private int[] mKeys;
private Object[] mValues;

它的实现与 ArrayMap 类似,因为它的 key 直接是 int 类型,省去了计算 hash 值的过程。可以直接将 key 值在 mKeys 数组中进行二分查找,以获得下标。再用这个下标到 mValues 数组中获得对象。

哈希表的应用

哈希表最关键的特征是,将数组的查值变成O(1)开销,因此遇到类似问题,我们应该有意识的构建哈希表。但要注意,在具体实现过程中,可能碰到 key 键重复问题

算法题:Two Sum

1
2
3
4
5
6
7
"""
Example:
Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
"""

常规解法是双循环,时间开销是O(n)。通过构建哈希表可以将其降低到O(1)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public int[] twoSum(int[] nums, int target) {
//1.构建哈希表
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
//2.在哈希表中查找差值
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[] { i, map.get(complement) };
}
}
throw new IllegalArgumentException("No two sum solution");
}

这个解法利用了哈希表的高效查找。值得注意的是这里所构建哈希表的元素是(值,索引),因为索引不可能相同,而值可能相同,所以数组中的相同元素在插入时,会被覆盖。

例如

1
int[] nums = {3, 3};

获得的 map 将是 { 3:1 }, 而不是{ 3:1, 3:0 } 。这样就存在一个隐患,所幸的是我们构建哈希表时被覆盖的是索引小的那个,查找时是根据索引小的那个查找索引大的那个,而且这个题目只要求查找出一对数就够了。

我们可以进一步思考下这个算法的关键步骤在哪里?

利用哈希表判断差值是否在表中存在的那一步,这一步本来都要起一个循环来判断的,因为我们构建并利用了哈希表,所以开销从O(n)降低到了O(1),但是正因为如此,哈希表的 key 值必须用数字值而不是索引值,随之而来的就是重复数字值在哈希表中被覆盖问题,这导致了我们无法用这种方法求出所有满足条件的结果。

历法

历法是根据天象(主要是日月)规律,计算时间(即年月日长度),以判断季节变化的法则。

历法的中心问题:年和月

制定历法所凭借的依据不外乎太阳和月亮的运动规律。是最容易观测的确定一个时间间隔,凡经历过一个日升月落即为一日。这似乎是确定无疑的,但要为一日确定一个起点,却又并不容易。古人逐渐发现可以通过直立杆的投影来解决这一问题,将一天之内投影最短的时刻定为正午,这样两个正午之间的时刻就是一日。

连续观测正午时刻直立杆的投影长度,就能够发现它是周期循环,这一循环的发现导致“年”的产生。此外还导致最初两个节气的产生:人们将投影长度最短的那一天叫做一年的夏至,最长的那一天叫做一年的冬至

对投影的观测实际是间接观测太阳,与之相比,月相的观测更加简单直接。月亮的盈亏也是一种周期循环,这导致“月”的产生。

现在我们知道,太阳直射点的变化周期,即一个回归年为365.2421897日,月亮绕地球运行的周期,即朔望月,大约29.530588日。二者都不是整数,且不能整除,使得一个回归年不能平摊成整数个朔望月。这导致太阴历法和太阳历法都有一定的缺陷。

太阳历和太阴历的缺陷

就太阴历而言,它以月相周期定月,12个朔望月为一年,这样一年约354或355日,这样每年会短缺11日左右。只要16个阴历年左右,就会差距到180多天,即半年左右,就会发生6月下雪、腊月天旱、冬夏倒置的毛病,对农业生产没有指导意义。太阴历的这种弊端之由来在于完全忽视了回归年,而回归年又是四季的依据。在文明开始之初,因为月亮便于观测,太阴历曾被广泛采用,但随着使用过程中的问题暴漏,逐渐被放弃。

就太阳历而言,它以回归周期定年,不依据月相,分一年为12个月,有大小月之分,这个“月”和朔望月完全无关。太阳历比太阴历问题少,它符合四季规律,但是月相的变化与月完全不能合拍。此外对于古人而言,回归年并不是整数日,这意味着随着年的累计,太阴历上的问题也会到来,只不过速度比较慢而已。

古埃及因为尼罗河泛滥的原因,非常重视天文学和历法的制定。他们在7千年前,已经把回归年定为365天。然而这个时间与真实的回归年相差0.24天,这意味着每100个回归年之后,历法上便少计24天,大约700多年后,就会出现与太阴历相同的冬夏颠倒的情况。这一情形需要再过700多年才能纠正。循环周期长达1461年。

连分数与闰年

连分数的意义在于把实数(如5.0989)变成纯粹的数学形式。与小数表示形式相比,连分数可以进行截断逼近。例如

把回归年数写成连分数形式

这里是前三次逼近结果,由此我们可以知道如何通过置闰的方式解决回归年周期问题。回归年取近似值$\frac{1}{4}$ 意味着每 4 年太阳历会比回归年少 1 天,因此要每4年置闰一天。这是第一步的近似。更精确的近似是$\frac{7}{29}$ ,即每 29 年太阳历会比回归年少 7 天,因此经过 29 个太阳历年后需要外加上 7 天之后才能开始下一回归年。对于第三个分数,就是每 33 年后需要加 8 天,也等于 99 年加 24 天。

如果取第一级截断近似,就是每 4 年一个闰年,闰年里将 2 月变为 29 日来增加一天。这个数值略大于回归年,会产生每年 0.008 天的差距,这样100年近似于1天,大约2万2千年之后进入冬夏颠倒的混乱期。这个误差人们还是不能忍受,于是要每过一百年减去 1 天来进行补偿,即百年不设闰。这样每年的差距实际只有 0.0002 天的差距,混乱周期扩大到百万年级别,可以认为是非常精确了。

这里还有最后一个问题:近似是 99 年加 24 天,实际采用百年不设闰,二者是有差别的。每隔 400 年,添加了天数为 24 4 天,这样差距为 0.002 天,仍然很大。所以设置*每 400 年置闰,差距变为 0.00031 天,接近 $\frac{8}{33}$ 的效果。

农历闰月

农历是一种阴阳历,年采用回归年,月采用朔望月,因此需要安排闰月来调整。公历则无此需要,因此公历的月不会与月相变化相吻合。

在一个回归年年,每年的月数是 12.36826, 写成连分数为

这里 $\frac{7}{19} = 0.36842$ 已经非常接近,每年会产生 0.00016 个月的差距。此即 19年7闰

历史上的历法

公元前45年罗马皇帝儒略·凯撒在埃及天文学家协助下创立的儒略历,设置四年一闰。从前面的描述我们知道儒略历并不非常精确,4个回归年的零数积累在一起,为23时15分4秒,还不足一日,尚差44分56秒。由于累积误差随着时间越来越大,根据前面的推算,到 1582年改历那天,儒略历在1600年里产生大约 10 天的误差

1582年罗马教皇格里高利十三世制订格里高利历,也叫公历。“四年一闰”每400年就将相差三日。为此,每400年必须少闰三次。设置97个闰年。公历亦称阳历,与中国传统农历(阴阳历)不同。

改历前后的历史事件和文件有造成混乱的可能。

中国历史上一共产生过102部历法,如夏历、商历、周历、西汉太初历、隋唐大衍历和皇极历等。汉代之前的历法就采用阴阳历,即“古六历”(黄帝、颛顼、夏、殷、周、鲁)中的《颛顼历》,以365又1/4日为一回归年,以29又499/940日为一朔望月, 19年中置7个闰月。由于这种古历计算不够精密,常出现月初朔日,但实际天空中却有圆满的月光;月中望日,夜晚却并没有月亮。为了改变这种不对照的现象, 司马迁主持制订《太初历》。

汉朝初年沿用秦朝的历法颛顼历,以农历的十月为一年之始,因历法与天象运行正朔失合,司马迁在公元前104年(汉武帝元封七年)上书,“言历纪坏废,宜改正朔”。汉武帝“乃诏迁用邓平所造八十一分律历,罢尤疏远者十七家”。并将元封七年改为太初元年。

太初历》测算出一朔望月等于29又81分之43日,故又称为“81分律历”。以冬至所在之月为11月,改秦历以10月为岁首的错误,以正月为岁首,12月底为岁末,并首次将24节气订入该历法,与春种、秋收、夏忙、冬闲的农业节奏合拍,春生夏长,秋收冬藏,四季顺昌。落下闳在预见《太初历》不足之处曾指出:“日后八百岁,此历差一日,当有圣人定之。”(实际上仅一百余年即误差一日)。落下闳计算《太初历》即采用前述“连分数”的数学原理。

正朔

正朔是历法定年定月之基础。正者,岁之始也,朔者,月之始也。一年的第一个月称作正月,一月的第一日称作朔日。上古之时,计算历法与授时被认为是与上天沟通的重要形式,只有部落领袖和统治者才有权进行。甚至于直到清代,私习天文都被认为是有谋反之意。改年号与颁历法仍然是皇帝体现权力的重要手段。旧时历书称为皇历,盖因历书必由皇帝所颁。

因为正朔是天子权力象征,所以在王朝更迭之际,奉何正朔也同时表明了政治取向。例如,孔子在《春秋》中,每年之初必称“某年春王正月”,《公羊传》:“春者何?岁之始也。王者孰谓?谓文王也。曷为先言王而后言正月?王正月也。何言乎王正月?大一统也。”也就是说,鲁尊周文王所定之正朔,以示鲁忠于周。而因鲁桓公弑君而立,桓公三年至八年,及十一年至十七年,《春秋》只称“某年春正月”,曰桓无王也。

秦历十月开始一年, 自汉武帝正式使用年号,颁布太初历,改用夏正以后,后世两千多年的帝王一般只改年号而不改正朔,只有武则天,太平天国等改正朔。很多文献都称,今日所用之华夏历法就是夏历,但现行华夏历法已有演变,事实上今日之历法只是沿用了夏正,而没有用夏朔。夏以天明为朔,商以鸡鸣为朔,周以夜半为朔,体现了计时的进步;

节气

中国古代利用土圭实测日晷,将每年日影最长定为“日至”(又称日长至,即太极图中四象的太阴、长至、冬至),日影最短为“日短至”(又称短至、夏至)。在春秋两季各有一日的昼夜时间长短相等,便定为“春分”和“秋分”,人类各民族多有此四。在商朝时只有四个节气(四象,即四季),到了周朝时发展到了八个(八卦),到秦汉年间,二十四节气已完全确立。公元前104年,由邓平等制定的《太初历》,正式将二十四节气订于历法,明确了二十四节气的天文位置。

二十四节气每一个分别相应于太阳在黄道上每运动15°所到达之位置。二十四节气又分为12个节气和12个中气,一一相间。二十四节气反映了太阳周年视运动,所以其西历日期近乎固定,上半年的节气在6日,中气在21日,下半年的节气在8日,中气在23日,前后不差1~2日。二十四节气的命名反应了季节和气候的变化。立春、春分、立夏、夏至、立秋、秋分、立冬、冬至,又称八位,是区分公转运动对于地球影响的八个关键节点;

1
2
3
4
5
6
7
8
春雨惊春清谷天;
夏满芒夏暑相连;
秋处露秋寒霜降;
冬雪雪冬小大寒。
每月两节不变更;
最多相差一两天;
上半年来六廿一; // 上半年的节气在6日,中气在21日
下半年来八廿三。 // 下半年的节气在8日,中气在23日

Typora 的使用其实都在 帮助 菜单里,本文是其中的一些总结, markdown 的基本语法不再提及。

大纲视图

在视图菜单里可以调节各种视图。

一些符号

KBD

Command

效果

1
<kbd>Command</kbd>

Task List

1
2
- [ ] incomplete
- [x] completed

效果

  • [ ] incomplete
  • [x] completed

Footnotes(脚注)

脚注,有悬停标注的特性,适合于解释某些名词,例如

相对论是爱因斯坦1创立的。

通过【段落】- 【脚注】操作

1
2
3
相对论是爱因斯坦1创立的。

[^1]: 德国物理学家,诺贝尔奖获得者。

高亮

文本高亮首先要在 【文件 - 偏好配置】,打开 【扩展语法 - 高亮】,而后

==高亮文本==

1
==高亮文本==

HTML 元素

以上还只是在 Typora 给定范围内的功能,实际上 Typora 本身是个能解析 Html 的“浏览器”,这个软件界面包括菜单项都是 Html 元素,使用者所编写的 markdown 语句最终也被解析成了 html 元素而已。

我们打开【视图-开发者模式】就会看到类似于 chrome 开发者模式的控制台,

可见标题 【Block Elements】是以 h2 和 span 标签的形式嵌入到 html 文档中的。

利用这一点,我们可以直接插入 Html ,并利用 CSS 属性改变样式。

例如我们借助 video 标签插入一段视频

1
<video src="..\img\got.mp4" />


Bilibili上的视频直接可以得到嵌入代码,非常容易插入,例如

1
2
<iframe height="600" width="100%" src="//player.bilibili.com/player.html?aid=48521546&cid=84967122&page=1" allowfullscreen="true" > 
</iframe>


再例如我们要插入一段蓝色文本,可以采用内联样式

国际米兰的颜色是蓝色和黑色。
1
<div align="center">国际米兰的颜色是<span style="color:blue"><b>蓝色</b></span>和黑色。</div>

因为我们无法操作 head 标签,所以无法采用内部样式表和外部样式表的方式来改变样式。

图片

插入图片可以直接拖拽,也可以使用【编辑-图片工具-插入本地图片】操作。生成的 markdown 语法如下

1
![outlineView](..\img\outlineView.png)

如果要改变图片的显示方式,就不能采用这种方式了。应该直接使用 img 标签,这样可以通过修改样式来改变图片的大小和对齐方式

1
2
3
<div align="center">
<img src="http://img.mp.itc.cn/upload/20170105/d05be7e27f414afc90940ef7da148ddd_th.jpg" alt="改变图片大小和对齐" style="margin:3px;border:2px solid #be5abe;width:600px;height:300px; "/>
</div>
改变图片大小和对齐

这里为了实现对齐,添加了一个 div 元素。也可以采用简化操作

1
2
3
<center>
<img src="http://img.mp.itc.cn/upload/20170105/d05be7e27f414afc90940ef7da148ddd_th.jpg" alt="改变图片大小和对齐" style="zoom:50% "/>
</center>
改变图片大小和对齐

在插入图片的时候,选择【编辑-图片工具- 图片设置】,选择将图片复制到指定文件夹,可以保存图片

主题和CSS

打开【文件 - 偏好设置 - 主题文件夹】可以发现主题 CSS 文档,通过修改参数可以定制主题。

Typora 使用 CSS 文档的顺序如下:

  1. Typora’s basic styles.
  2. CSS for current theme.
  3. base.user.css under theme folder.
  4. {current-theme}.user.css under theme folder. eg:github.user.css

在主题文件夹中创建 base.user.css 和 {current-theme}.user.css 即可以实现改变样式属性的目的。例如在 github.user.css 文件中写入

1
2
3
span {
color: #f484c1;
}

即可以改变所有 span 标签的文本颜色。但是这种方法无法使用 id 和 class 选择器

文字从右向左

添加以下 CSS 代码即可。

1
2
3
#write {
direction: rtl;
}

效果如下

​ 文字从右向左

这个效果虽然简单,其中使用的 id 选择器却值得注意, 翻阅源码可以发现,整个内容文本都被放置在 id 为 “write” 的 div 块元素中 。这段 CSS 代码就是针对内容区所有对象进行设置。

另外,如果我们自己添加元素,并设置 id 或者 class,如下

1
<p id="jack">好看撒大撒大撒啊</p>

这个 P 元素会被套在若干个 div 块里,所设置 id 和 class 属性都不会保留, 其它属性如 style 则可以保留并发挥作用。

背景图片

背景虽然不实用,但如果要设置,首先还是要寻找合适的纹理文件

纹理文件下载

[纹理文件下载]:

下载拷贝到主题文件夹,添加 CSS 代码

1
2
3
4
content {
background: url(./fzm-seamless.notebook.texture-06.jpg);
background-repeat: repeat;
}

代码块

调节代码块的意义更大一些,先给个效果图

添加如下 CSS 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
.cm-s-inner {
background-color: #263238;
color: rgba(233, 237, 237, 1);
}
.cm-s-inner .CodeMirror-gutters {
background: #263238;
color: rgb(83,127,126);
border: none;
}
.cm-s-inner .CodeMirror-guttermarker, .cm-s-inner .CodeMirror-guttermarker-subtle, .cm-s-inner .CodeMirror-linenumber { color: rgb(83,127,126); }
.cm-s-inner .CodeMirror-cursor { border-left: 1px solid #f8f8f0; }
.cm-s-inner div.CodeMirror-selected { background: rgba(255, 255, 255, 0.15); }
.cm-s-inner.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
.cm-s-inner .CodeMirror-line::selection, .cm-s-inner .CodeMirror-line > span::selection, .cm-s-inner .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }
.cm-s-inner .CodeMirror-line::-moz-selection, .cm-s-inner .CodeMirror-line > span::-moz-selection, .cm-s-inner .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }

.cm-s-inner .CodeMirror-activeline-background { background: rgba(0, 0, 0, 0); }
.cm-s-inner .cm-keyword { color: rgba(199, 146, 234, 1); }
.cm-s-inner .cm-operator { color: rgba(233, 237, 237, 1); }
.cm-s-inner .cm-variable-2 { color: #80CBC4; }
.cm-s-inner .cm-variable-3 { color: #82B1FF; }
.cm-s-inner .cm-builtin { color: #DECB6B; }
.cm-s-inner .cm-atom { color: #F77669; }
.cm-s-inner .cm-number { color: #F77669; }
.cm-s-inner .cm-def { color: rgba(233, 237, 237, 1); }
.cm-s-inner .cm-string { color: #C3E88D; }
.cm-s-inner .cm-string-2 { color: #80CBC4; }
.cm-s-inner .cm-comment { color: #546E7A; }
.cm-s-inner .cm-variable { color: #82B1FF; }
.cm-s-inner .cm-tag { color: #80CBC4; }
.cm-s-inner .cm-meta { color: #80CBC4; }
.cm-s-inner .cm-attribute { color: #FFCB6B; }
.cm-s-inner .cm-property { color: #80CBAE; }
.cm-s-inner .cm-qualifier { color: #DECB6B; }
.cm-s-inner .cm-variable-3 { color: #DECB6B; }
.cm-s-inner .cm-tag { color: rgba(255, 83, 112, 1); }
.cm-s-inner .cm-error {
color: rgba(255, 255, 255, 1.0);
background-color: #EC5F67;
}
.cm-s-inner .CodeMirror-matchingbracket {
text-decoration: underline;
color: white !important;
}

/**apply to code fences with plan text**/
.md-fences {
background-color: #263238;
color: rgba(233, 237, 237, 1);
border: none;
}

.md-fences .code-tooltip {
background-color: #263238;
}

我们写的代码块会被转化为一个复杂的 div 盒子,这个盒子的一个 class 属性就是 “cm-s-inner”,内部元素各有各的 class 命名,例如展示代码的行号的 div 盒子的 class 是 “CodeMirror-gutters”,因此这里给它设置的是一个二级匹配器。

字体

更改字体设置如下

1
2
3
body {
font-family: DFKai-SB; /** Microsoft Yahei UI **/
}

字体名称可以在 【C:\Windows\Fonts】目录下查看,也可以在 【设置-字体】中查找,例如微软雅黑的全名是 Microsoft Yahei UI。

下载新字体,例如徐静蕾字体,放入上述目录中即安装成功字体,此时查出此字体名称为 “方正静蕾字体”,即可以配置使用。

宽度

1
2
3
#write {
max-width: 1800px; /*adjust writing area position*/
}

打开 Tepora 是文本宽度将扩展到1800 px,可以调整打开时的视觉效果。

标题编号

添加如下 CSS 代码可以给各个标题自动生成编号,这个功能实际上并不怎么有用,但可以用来学习 CSS。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/** initialize css counter */
#write {
counter-reset: h1
}

h1 {
counter-reset: h2
}

h2 {
counter-reset: h3
}

h3 {
counter-reset: h4
}

h4 {
counter-reset: h5
}

h5 {
counter-reset: h6
}

/** put counter result into headings */
#write h1:before {
counter-increment: h1;
content: counter(h1) ". "
}

#write h2:before {
counter-increment: h2;
content: counter(h1) "." counter(h2) ". "
}

#write h3:before,
h3.md-focus.md-heading:before /** override the default style for focused headings */ {
counter-increment: h3;
content: counter(h1) "." counter(h2) "." counter(h3) ". "
}

#write h4:before,
h4.md-focus.md-heading:before {
counter-increment: h4;
content: counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) ". "
}

#write h5:before,
h5.md-focus.md-heading:before {
counter-increment: h5;
content: counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) "." counter(h5) ". "
}

#write h6:before,
h6.md-focus.md-heading:before {
counter-increment: h6;
content: counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) "." counter(h5) "." counter(h6) ". "
}

/** override the default style for focused headings */
#write>h3.md-focus:before,
#write>h4.md-focus:before,
#write>h5.md-focus:before,
#write>h6.md-focus:before,
h3.md-focus:before,
h4.md-focus:before,
h5.md-focus:before,
h6.md-focus:before {
color: inherit;
border: inherit;
border-radius: inherit;
position: inherit;
left:initial;
float: none;
top:initial;
font-size: inherit;
padding-left: inherit;
padding-right: inherit;
vertical-align: inherit;
font-weight: inherit;
line-height: inherit;
}

右键搜索

选中文本后,可以右键选择 google 搜索,但是没有翻墙是无用的。在【文件 - 偏好设置 -高级设置】中打开 【文件 conf.user.json】,加入

1
2
3
4
5
6
"searchService": [
["Search with Google", "https://google.com/search?q=%s"]
["Search with baidu", "https://www.baidu.com/s?ie=UTF-8&wd=%s"]
["Translate", "https://translate.google.cn/#view=home&op=translate&sl=auto&tl=en&text=%s"]
["Search with Wikipedia", "https://en.wikipedia.org/wiki/Special:Search/%s"]
],

四个选项分别是 Google搜索,百度,百度翻译,英文Wiki。

PanDoc

PanDoc 是一个标记语言的翻译器,例如能够将 Html 文本转换为 Wiki 文本。

PanDoc 使用方法

通过 PanDoc 比较重要的大概是我们可以直接将 md 文档转为 docx,pdf 等格式了,只要安装了 PanDoc 再使用 export 即可。


  1. 1.德国物理学家,诺贝尔奖获得者。

Quick Start

插入图片

1
{% asset_img slug [千与千寻的神隐] %}

插入PDF

1
2
$ npm install --save hexo-pdf
{% pdf polar.pdf %}

插入音频

1
2
3
<div align="center">
<audio src="11.mp3" controls="controls" autoplay="true" loop="true">新标日第11课</audio>
</div>

或者采用插件 hexo-tag-aplayer

1
2
{% aplayer title author url [picture_url, narrow, autoplay, width:xxx, lrc:xxx] %}
{% aplayer "新标日" "第11课" "11.mp3" "timg.jpg" %}

        

插入视频

1
<video src="got.mp4" controls="controls">冰与火之歌</video>

Create a new post

1
$ hexo new "My New Post"

Run server

1
$ hexo server

Generate static files

1
$ hexo generate

Deploy to remote sites

1
$ hexo deploy

html synchronizer

fetch remote webpage(including image file) and save to hexo post.

1
2
3
$ npm install hexo-html-syncer --save
# for example:
$ hexo syncer http://mp.weixin.qq.com/s/Tp4W-_0MXMvN5Tw3jlrtLg

auto-category

Automatically add front-matter categories to Hexo article according to the article file directory.

1
$ npm install hexo-auto-category --save
1
2
3
auto_category:
enable: true
depth:

从4s店女代表的发言可以看到,在闹出这么大动静之后,她依然是一副高高在上的态度,绝不认为己方有任何错误,所做的退让乃是施予客户的恩惠。

这个事出了之后,4s店内部有充足的时间准备,现在它们拿出这种态度来,说明它们对此事的处理原则就是抵赖推诿。由此可以想见它们一贯的行事原则,在坑蒙拐骗之余还问心无愧。

具体的事件自有相应的人和部门去善后,现在跳出具象谈谈一般的社会现象。

一切社会问题的本源就在公利和私欲上。作为社会的一份子,每个人追求私欲的本能是天生的和不择手段的,他维护公利的行为则是后天的和有所节制的,准确的说是在发现不维护公利不能保证自己的私欲的时候被动进行的。这样维护公利是作为追求私欲的前提存在,是一种无可奈何之举,因为人无此天性,公利又往往与私利相悖,欲使群体利益得到保障,必须要对个人施以教化。一般而言,受教育程度越高,越能明白公利之重要。按道理来讲,每个人都应该维护公利,然而这世界远非如此。

就商家消费者关系而言,整体消费者的利益是为公利,如果每一笔交易都能公平公正,全体消费者利益就能得到保证,因为此领域商家即为彼领域消费者,自然同受此惠。然而世间思来理所当然之事往往出人意表,付诸实施即谬以千里,何也?这是因为有这么一群人,并不承担公利义务,因而可以无节制追求私利,甚至以破坏公利为代价。求私欲而无视公利是一切社会问题的起源,不惟消费者市场如此。

现在的社会,一个人要想有尊严,有“排面”,那必须有钱,没钱则无“排面”。至于这钱是怎么来的,正义与否,合法与否,规则与否,并无人关心。于是我们看到蝇营狗苟之辈,各有稻粱之谋,所谓其不仁者富。反之一个人若是谨守良心,向不逾矩,则十有八九要忍饥挨饿,到那时他反而要受到奚落,他的讲道理受规矩反而在世俗中是一种羞辱。一个人即入了这种世道,他纵然有心向善,社会却必不叫他好看,他的落入不仁是可以预见的。

4s店女代表问”我们为什么要欺骗自己的上帝呢“,这话其实应该问她自己。所谓顾客是上帝只是一种营销话术,一般而言只有在你付款之前你才是上帝,如果售后也重视你,那只是还想做你下一笔生意罢了。这层遮羞布在中国尤其是一捅就破,顾客在此4s店眼里不惟不是上帝,亦或只是口头上帝,实际却是待宰肥羊。只要进了他这个门,就要掉一层皮。你不多出钱,它们卖车的,奔驰官方,搞金融放贷款的,甚至工商联等政府部门怎么有额外收入,怎么有业绩,又怎么有”排面“呢?

在社会的各种位置上,到处充斥着这种消费主义价值观所塑造的坑蒙拐骗之徒,阳奉阴违,笑里藏刀。而且我们知道,人在长时间尺度上终归是要归于自洽的,他纵犯有滔天罪恶,经过时间的熨烫,最终也能以理直气壮的面目出现。旧时的土匪不也管自己打家劫舍叫做吃这碗饭吗?吃饭是天经地义之举,自然打劫也就有理有据了。今日的4s店销售坑骗的人多了,自然早就从心理上开脱了自己。她既然没错,那错的必然是被她坑骗的顾客了。要问这些花了冤枉钱的顾客错在哪里?错就错在其它人被坑了都不闹事,偏偏就你闹事。这就是人的异化。这一点在今日的资本家群体身上尤其明显,经过反复的拉锯和试探,资本家已经不认为996是违反劳动合同法之举,而是他施予的福报。不接受996就是没有拼搏精神,把一件他自己无理之事变成劳动者的罪过。

对此情形,政府存在不可推卸的责任。人性本恶,因此法家主张严刑峻法以绝人之恶,以赏罚二柄塑造人的行为,使其导入农战二事。今天的政府几无作为。消费者和劳动者权益保护的远远不够,劳动合同法形同虚设,315做成了一门生意,资本家可以随意做伪证不受处罚,因此像顺丰这种无良公司可以随意践踏劳动合同。如果政府真的有心维护消费者劳动者权益,只要加大对此类行为的处罚力度,实施惩罚性罚款等,这些大大小小的骗子们自然趋利之余要兼顾避害,不敢如今日之肆无忌惮。

从政府对房价的调控来看,他们实际是不愿意真的降低房价,反应在行为上就是拖延,逼不得已出招时也是怪招频出,转走偏门,不抓实质,最后自然也不能真的把房价调控下来。在消费者劳动者权益问题上亦然,我相信中央政府层面还是有此理想的,但地方政府则利益牵涉太深,保护劳动者消费者权益就要背上一个破坏营商环境的罪名,而原本的税源就有影响,即使不考虑背后的利益输送,也有害于官员的业绩指标。因此它们本质上是即无心又无力,做起事来荒腔走板,不出事故不干事,息事宁人之后依然故我,指望他们是不切实际的。

虽然前景是悲观的,但不代表这种私欲侵害公利的现象就会永远持续下去。公利本是维护公众利益的,侵之愈急,后报越大,亿万兆民,概莫能免。比如消费主义越盛行,贫富分化越严重,女性要求的彩礼越高,底层的生育权利越萎缩,新的韭菜阶层不敷收割之用,未来的中国将无法避免走上引入移民之路,用夷变夏,绝非虚言。

引入

1
2
3
4
implementation 'com.blankj:utilcode:1.25.9'

// if u use AndroidX, use the following
implementation 'com.blankj:utilcodex:1.25.9'

工具函数采用多种重载方式可以满足不同需求。

Android

Activity

启动

1
ActivityUtils.startActivity(Main2Activity.class);

转向桌面

1
ActivityUtils.startHomeActivity();

获取活动

1
2
3
4
5
6
7
List<Activity> activities = ActivityUtils.getActivityList();

Activity activity = ActivityUtils.getTopActivity();//栈顶 Activity
String activity = ActivityUtils.getLauncherActivity();//启动项 Activity

Activity activity = ActivityUtils.getActivityByView(view);//根据视图获取 Activity
Activity activity = ActivityUtils.getActivityByContext(view.getContext());//根据上下文获取 Activity

结束活动

1
2
3
4
5
6
ActivityUtils.finishActivity(this);
ActivityUtils.finishActivity(Main2Activity.class);

ActivityUtils.finishOtherActivities(Main2Activity.class);//结束所有其他类型的 Activity

ActivityUtils.finishAllActivities();//结束所有 Activity

Service

类似

1
ServiceUtils.startService(MyService.class);

Fragment

1
FragmentUtils.add                   : 新增 fragment

Snackbar

1
2
SnackbarUtils.with(v).setMessage("SnackBar").show();
SnackbarUtils.with(v).setMessage("SnackBar").showError();

Toast

1
ToastUtils.showShort("Toast");

SpannableString

1
SpannableStringBuilder builder = SpanUtils.with(textView).setStrikethrough().setFontSize(24).append("liuxiang").create();

SharedPreferences

1
2
3
4
SPUtils spUtils = SPUtils.getInstance();

spUtils.put("name", "liuxiang");
String name = spUtils.getString("name");

App

安装,启动App

1
2
public static void installApp(final String filePath);
public static void launchApp(final String packageName)

App 信息

1
String name = AppUtils.getAppName();

状态栏和导航栏

高度和颜色

1
2
3
int statusHeight = BarUtils.getStatusBarHeight();
int naviColor = BarUtils.getNavBarColor(getWindow());
int actionBarHeight = BarUtils.getActionBarHeight();

判断可见与否

1
boolean isVisible = BarUtils.isStatusBarVisible(this);

改变高度和颜色

1
2
BarUtils.setStatusBarColor(this, 0xff78ff);
public static void setStatusBarColor4Drawer(final DrawerLayout drawer, final View fakeStatusBar, final int color) //为 DrawerLayout 设置状态栏颜色

权限

所有的危险权限:

img

申请动态权限的正常逻辑是

1.先检查权限是否已经授权,如果已经授权,即可跳过后面步骤

2.再检查是否要提示UI,一般误操作点击“禁止”按钮后,此检查为真。

3.如果不需要提示UI,或者在提示UI里同意请求权限,则使用 ActivityCompat.requestPermissions。

4.最后在回调,方法里处理权限结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PERMISSION_GRANTED) {
Log.i("ContextCompat", "检查权限状态 ");
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
Log.i("ContextCompat", "用户未彻底拒绝授予权限, 一般会提示用户进入设置权限界面 ");
new AlertDialog.Builder(MainActivity.this)
.setTitle("提示")
.setMessage("应用需要开启拍照的权限,是否继续?")
.setPositiveButton("确定", -> {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
})
.setNegativeButton("取消", -> { }
}).show();
} else {
Log.i("ContextCompat", "用户未彻底拒绝授予权限: ");
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
}
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 1) {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PERMISSION_GRANTED) {
Log.i("ContextCompat", "申请成功: "+permissions[0]);
} else {
Log.i("ContextCompat", "申请失败: "+grantResults[i]+" "+PERMISSION_GRANTED);
}
}
}
}

使用 PermissionUtils 可以简略如下,经过封装回调函数,不需要写两遍执行代码,也不需要继承权限回调方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private void requestRecordAudio() {
PermissionUtils.permission(PermissionConstants.STORAGE)
.rationale(new PermissionUtils.OnRationaleListener() {
@Override
public void rationale(final ShouldRequest shouldRequest) {
Log.i("ContextCompat", "rationale: ");
new AlertDialog.Builder(MainActivity.this)
.setTitle("提示")
.setMessage("应用需要开启拍照的权限,是否继续?")
.setPositiveButton("确定", -> {
shouldRequest.again(true);
})
.setNegativeButton("取消", -> { })
.show();
})
.callback(new PermissionUtils.FullCallback() {
@Override
public void onGranted(List<String> permissionsGranted) {
String time = TimeUtils.millis2String(System.currentTimeMillis());
textView.setText(time);
Log.i("ContextCompat", "申请成功: ");
}

@Override
public void onDenied(List<String> permissionsDeniedForever, List<String> permissionsDenied) {
Log.i("ContextCompat", "申请失败: ");
}
})
.request();
}

设备

像素(pt:每英寸像素数)

1
2
int px = AdaptScreenUtils.pt2Px(100); //569
int pt = AdaptScreenUtils.px2Pt(100); // 18

亮度

1
2
int bright = BrightnessUtils.getBrightness();
int windowBright = BrightnessUtils.getWindowBrightness(getWindow());

颜色

1
public static int getColor(@ColorRes int id);

内存缓存

1
CacheMemoryStaticUtils.setDefaultCacheMemoryUtils(CacheMemoryUtils.getInstance());

读写

1
2
int name = CacheMemoryStaticUtils.get("name");
CacheMemoryStaticUtils.put("name","liuxiang");

磁盘缓存

创建

1
2
//Instance.getCacheSize  可以获取缓存大小
CacheDiskStaticUtils.setDefaultCacheDiskUtils(CacheDiskUtils.getInstance());

写入

1
CacheDiskStaticUtils.put("name","liuxiang");

读取

1
String name = CacheDiskStaticUtils.getString("name");

Clean

1
2
3
4
5
CleanUtils.cleanInternalCache();//清除内部缓存
CleanUtils.cleanExternalCache();//清除外部缓存
CleanUtils.cleanInternalDbs();//清除内部数据库
CleanUtils.cleanInternalSp();//清除内部 SP
CleanUtils.cleanCustomDir(File);//清除自定义目录下的文件

键盘

1
KeyboardUtils.showSoftInput(MainActivity.this);

震动

1
VibrateUtils.vibrate(2000);

Java

数组

创建各种类型数组

1
2
3
4
int[] nums = ArrayUtils.newIntArray(1,2,3,4);
char[] chars = ArrayUtils.newCharArray('a','b','c','d');

Character[] chars = ArrayUtils.newArray('a','b','c','d');//泛型接口

检空和长度

1
2
3
4
5
boolean isEmpty = ArrayUtils.isEmpty(chars);

int len = ArrayUtils.getLength(chars);
boolean isSameLength = ArrayUtils.isSameLength(nums, chars);//判断长度是否相等
boolean isSameLength = ArrayUtils.equals(nums_1, nums_2);

排序和逆序

1
2
ArrayUtils.sort(nums);
ArrayUtils.reverse(chars);

取值和写入

1
2
3
4
5
int num = (int) ArrayUtils.get(nums, 3);
ArrayUtils.set(nums, 3, 13);

ArrayUtils.add(nums_1, nums_2); //批量添加
ArrayUtils.subArray(nums_1, 2, 4); //截取数组

字符串

检空

1
2
3
boolean isEmpty = StringUtils.isEmpty("");
boolean isTrim = StringUtils.isEmpty("");
boolean isSpace = StringUtils.isSpace("");

空转0

1
2
String nul = null;
String zeroLen = StringUtils.null2Length0(nul);

判等

1
2
boolean isEqual = StringUtils.equals(s1, s2);
boolean isEqual = StringUtils.equalsIgnoreCase(s1, s2);//判断两字符串忽略大小写是否相等

文件

读写

1
2
String file2String = FileIOUtils.readFile2String("filepath");//读取文件到字符串中
List<String> file2List = FileIOUtils.readFile2List("filepath");//读取文件到字符串链表中

相关操作

1
2
public static File getFileByPath(final String filePath);//根据文件路径获取文件
public static boolean isFileExists(final String filePath);

URI

1
2
Uri uri = UriUtils.file2Uri(file);
File file = UriUtils.uri2File(uri);

路径

1
String esp = PathUtils.getExternalStoragePath();//外存路径

时间

1
String time = TimeUtils.millis2String(System.currentTimeMillis());//将时间戳转为时间字符串

图片

1
Bitmap  des = ImageUtils.toRound(bitmapSrc);

总线

注册

1
2
public static void register(final Object bus);
public static void unregister(final Object bus);

发送

1
public static void post(final String tag);

成表

 a   ai   ao   an   ang 
ゃ・あつ・お あい お・よ・おく あん・えん・いん お・よ
茶・圧・甲 高・超・告 安・船・員 棒・長
圧縮・あっしゅく 彫刻・こく 報告 観光客・かんこうきゃく 王・張
 i   ie   iu   in  ing
い・あい・えい\ いつ・えき\ ゆ・よく ゃ・あい・よ・えつ いん えい・よ
体・器・喫・計・急・席・食 解決・謝・協 名・病
気温・きおん 地域・ちいき 季節・きせつ 英・
 u   ui   ue   uo   un 
お・う【いく・おく・よく【いき・よ い・あい・うい・えい あく・やく【えつ あ・あく・あつ オン・ユン・ウン・イン
図・族・・宇・育・初・局 貴・会・水・税 学・ 果・拡・活 遠・春・君・菌
都府・とふ 音楽・がく
 e   ei   en   eng   er 
あ・や】あく・おく】えつ あい・い いん・うん えい・お・よ
課・格・・者・ 杯・非 眞・聞 冷・能・省
冊・さつ 温泉
性格(せいかく) 委託(いたく)
 o uo   ou   ong   iong 
あ・あく・あつ お・ゆ お・ゆ・よ えい・よ  
作・握・活 欧・州 東・中・兄 兄・兄  
悪魔・あくま 握手・あくしゅ 永遠・えいえん  

理论基础

古代日本只有语音而无文字,唐代通过遣唐使引入汉字作为文字,其中汉字的汉语读音称为音读,原本的日语读音称为训读

由于日语借鉴的是古汉语,主要分为流传于北方长安地区的陕音和南方的吴音,所以现代汉语和日语系出同源,虽然经历了各自流变有所不同,但又存在隐秘的联系。

汉语采用声韵注音,日语音读也遵从此规律。日语汉字的音读可以总结为FXP模式

  • F 即声部,一般是辅音或缺失
  • X 即韵部,一般是元音,以及 や、よ、ゆ计 8 种
  • P 即韵尾,只有 8 种。即 い段(い、き、ち)う段(う、く、つ、っ)、实际一样表示长音,读时不发音。

韵尾分布

つ・っ

只有首行以及k,t行い段和う段共 6 个假名可以作为汉字音读的结尾。结合韵部元音只有 8 个来看,那么日文韵部整体只有 8*8 = 64 种可能。而实际使用的则更少,只有 32 种。

禁止
あい あち あく あつ あん き・う
いき いち いく いつ いん い・う
うい うく うつ うん き・ち
えき えち えつ えん い・く
おく おつ おん
やく
ゆい ゆく ゆつ ゆん
よく

韵部变化

日文汉字的音读本来是汉音或吴音的发音,只不过声韵部在各自流变过程中发生了很大变化,如果能找出这些变化规律,就可以从日文汉字的汉语音推测出它的日语音

元音 a

以元音 a 为主体的韵部有:a(ia,ua,ya),ai(uai),ao(iao),an(uan,ian),ang(uang, iang) 5类。

中文韵母(a) 例词 例子  日语变音
a、ya、ia、ua   家・価・華(か)
警察署・けいさつしょ 殺・刷(さつ)、速達(そくたつ) あつ
雑誌(ぞう)  お
ai、uai    快(かい)、依頼(いらい)  あい
ao、iao  交・好(こう)、報(ほう)   お 
  教授、少(しょう)、消防(しょう ぼう しょ)   よ 
  告(こく) 薬 薬局・やっきょく  おく 
an、uan、ian  安全ざん  国・品、暗算・ざん、番・ばん  あん 
  戦船  生、筆、話、周、以前・いぜん、減・げん、面・めん、永遠・えいえん 延期 演技 園芸 遠足・えんそく  えん 
  便局   いん 
ang 、iang 蔵庫  棒(ぼう)、装(そう)、想(ぞう) 、光(こう)、象・ぞう 放・ほう 黄・皇 消防(しょう ぼう しょ) お 
(zh、ch、sh)    上、嬢(じょう)、将(しょう)、両(りょう)、様・洋・よう 工場(こう じょう)  よ 
  相  相方、相手、  あい 

下面简易版只需要记忆 12 个例字即可。

中文韵部 a(ia,ua,ya) ai(uai) ao(iao) an(uan,ian) ang(uang, iang)
日文假名 あ、あつ、お あい お、よ、おく あん、えん、いん お、よ
日文韵部 a, atu, o ai o, yo,oku an, en, in o, yo
例字 茶、圧、甲 高、超、告 安、船、員 棒、長

使用举例

報告

二者都是 ao 结尾,ao的例字是“高 超 告”,有三个日文变音 “お よ おく“,这样我们在不知道其日文发音的情况下可以使用日文输入法试出其音读发音。

我们首先采用中文声母 b + ou,一般而言,原始中文声母都不能和日本音读配对,必须寻找其临近的日文变化,日文里,b是h行变化来的,这里我们再采取 h + ou,即可以得到

元音 i

i 共计 i,ie,iu,in,ing 五个韵部。

中文韵母(i) 例词 例子  日语变音
i  際(さい)、育、済・ざい 米(べい)  あい 
  衣・以  機、気、地・ち 日・ひ  い 
  、湿度・質・しつ、   いつ 
  芸(げい)、隠蔽・いんぺい えい 
  急(きゅう) 夕 朝夕・あさゆう ゆ 
  式(しき)、席・石・責 えき 
  堂、極(きょく)、移植・いしょく   よく 
  市役所・やく   やく 
ie  世界・せかい 一切(いっさい) あい 
  結(けつ)、季節(せつ)、送別・そうべつ  えつ 
  あい(ai) 
  協(きょう)   よ 
iu、iou  理、酒・しゅ 流(りゅう)  
in    いん
ing  産品 英(えい)、刑、経(けい)、歓迎、安静 影響・きょう 星・せい  えい 
  院、行(ぎょう) 愛情(じょう)  よ 

其中 i 的变音有 7 个,一共需要掌握 15个例字。

i ie iu(iou) in ing
あい、い、いつ、えい、ゆ、えき、よく あい、えつ、や、よ いん えい、よ
ai, a, itu, ei, yu, eki,yoku ai, etu, ya, yo yu in ei, yo
体、器、喫、計、急、席、食 解、決、写、協 名、病

使用举例:

ji -> (体、器、喫、計、急、席、翼) -> き 

家庭

ting -> 名、病 -> (えい, よう )  -> てい 

元音 o

中文韵母(o) 例词 例子  日语变音
o、uo  作(さ) 魔・ま あ 
  握・悪(あく)  作(さく),博(はく)物(ぶつ)館  あく 
  活(かつ)  末・抹・まつ あつ 
ou  欧州(おうしゅう)  口(こう) 応援(えん)、温厚(こう)  お 
  辺、宙(ちゅう) ゆ 
ong  東(とう) 園、工(こう) 同(どう) 運送(そう)、永・詠美 えいみ  お 
  国人 終(しゅう)、中(しゅう) 一種(しゅ) 英雄(ゆう)  ゆ 
  送・そう よ 
iong  泳(えい) 種類・しゅるい えい 
  兄(きょう) よ 
   

松島・まつ

中文韵部 o(uo) ou ong iong
日文假名 あ、あく、あつ お、ゆ お、ゆ、よ えい、よ
日文韵部 a, aku, atu o, yu o, yu,yo ei, yo
例字 作、握、活 欧、州 東、中、 兄、兄

o 只有 o,ou,ong,iong 四个读音,10个例字。

選手 -> shou -> (欧洲) -> (おう、ゆう) -> しゅ 

元音 e

中文韵母(e) 例词 例子  日语变音
e  歌(か) 業・ぎょう  あ 
  場合・ば   
  格(かく) あく 
  特・徳・とく おく 
    や 
  設計・せっけい、右折・うせつ  えつ 
ei  杯(はい) 曖昧・あいまい、内・ない あい 
  非(ひ) 意味・み 維持・いじ 偉大・いだい 威圧(あつ) 美術館・び い 
  衛生、衛星 えい 
  北 北海道・ほっ おく 
en    いん 
    、部分・ぶん 温室(しつ) おん 
eng  蔵庫 徒、成、誠(せい)、程(てい)、台風・ふう  えい 
  能(のう) 崩(ほう)、層(そう)、耕(こう)  お 
  乗(じょう) 承、勝、省(しょう)  よ 
er  児(じ)    い 
中文韵部 e ei en eng er
日文假名 あ、あく、おく、や、えつ あい、い いん、おん えい、お、よ
日文韵部 a, aku, oku, ya, etu ai, i in, on ei, o, yo i
例字 課、格、刻、者、説 杯、非 眞、聞 冷、能、省

e 共计 e,ei,en,eng,er 五个韵部,共计 13 个例字。

元音 u

中文韵母(u) 例词 例子  日语变音
u    ウイ  お 
  速(そく) 木・目・もく 毒・独・どく  おく 
    いき 
  体育・たいいく 菊・きく 陸・りく 建築・けんちく  いく 
  宇・羽  区・く  う 
  書 辞書・じしょ、入・にゅう よ 
  玉・ぎょく よく 
  主・しゅ 主要・よ、住所・じゅうしょ 駐車場(ちゅう) ゆ 
ui  貴  帰・貴(き)  い 
  回  あい 
  睡(すい)  うい 
  税(ぜい) 恩恵(けい) えい 
ue  学 学校・がっこう あく 
  楽・がく えつ
  あく 
uo    あ 
  拡・かく 郭、着・ちゃく、国・こく 委託(たく) あく 
  括・かつ 生活・せいかつ あつ 
un uen  遠  婚(こん)、損(そん)  おん 
  春(しゅん) 瞬(しゅん)、準、旬(じゅん)、循環・じゅうかん  ゆん 
  均(きん) 訓・くん、菌  いん(in) 
  運(うん)  軍(ぐん)、君  うん(un) 
中文韵部 u ui ue uo un(uen)
日文假名 お、おく、う、いき、いく、よ、よく い、あい、うい、えい あく、えつ、やつ あ、あく、あつ おん、いん、うん、ゆん
日文韵部 o, oku, u, iki,iku, yo, yoku i, ai, ui, ei aku, etu, yatu a, aku, atu on, in, un, yun
例字 図、族、域、宇、育、初、局 貴、会、水、税 学、悦、約 果、拡、括 温、君、菌、春

声部变化

日文声部总计不过10来个,其中使用最多的是 k 和 s 行。

以“ yan ” 音为例,

实际为 “ian = an”,变音有三。即日文汉字中文发音为“yan”者可能有三种读音

  • アン 安・暗・案 只有三个
  • エン 煙・塩・延 大部分字都是此音
  • イン 員  只有一个

常用汉字表

日本文化厅公布的常用汉字表,共2136字。

元音 a 相关汉字

a ア・茶 ia,ua 亜 加・価・か 華・か
アツ・圧
オ・甲・コウ
ai アイ・愛 ai
uai
guai 怪・改・かい
ao オ・高 ao
ヨ・超
an アン・安 an 案・暗
エン・船 yan 延期・沿海・焔・宴会・煙・塩
yuan 円・遠・援・園
ian 鉛・
イン・員
ang オ・棒・ボウ
ヨ・長

使用实例

我们读到一篇日语文章,遇到不认识的汉字,可以用这个方法”猜“出其读音。例如

イタリア・セリエAのインテル・ミラノに所属するサッカー日本代表DF長友佑都選手が4月19日、インスタグラムを更新。夫人で女優の平愛梨さんとの2ショット写真を投稿している。

  •  しょぞく 训读+音读
  •  だいひょ 
  • 選手 せんしゅ 
  • 更新 こうしん 
  • 女優 じょゆう
  • 投稿

「妻と一緒にディナーに行きました!」と報告する長友選手。ふたりは笑顔で寄り添い、顔を近づけて写真におさまっている。仲睦まじい様子がうかがえる一枚だ。

  • 報告 ほうこく 

  • 笑顔 しょう がん(かお)えがお

私は すき焼きを 食べた ことが あります

动词た型,几乎完全等于て 型。

  • 北京へ 行った ことが ありますか?
    •  いいえ、一度も 行った ことが ありません。
  •  映画を見た 後で、食事を しました。
  • 野菜を 食べた ほうが いいです。 
  • 野菜を 食べないほうが いいです

歌舞伎

森さんは 毎晩 テレビを 見る

动词敬体型 = ます型 ,简体型按照时态依次为 基本型、ない型、た型、なかった型。

  • ます:一类动词い段,二类动词段+少量段い,三类动词します。 
  • 基本:一类动词ます型去掉ます为い段,变为基本型改为う段;二类动词+る。
  • ない:二三类+ない,一类变あ+ない ,例外,い变わ+ない 
  • た:同て、二三类直接+,一类有变音 
  • なかった:
  • て:二三类直接+て,一类有变音
  • 買います - 買う 
  • 買いません ‐ 買わない 
  • 買いました ‐ 買った 
  • 買いませんでした - 買いなかった

一类形容词

  • 忙しいです - 忙しい 
  • 忙しく ないです ‐ 忙しく ない 
  • 忙しかったです ‐ 忙しかった 
  • 忙しく なかってです ‐ 忙しく なかって

二类形容词+名词

  • 簡単です - 簡単だ
  • 簡単では ありません - 簡単では ない 
  • 簡単でした ‐ 簡単だった
  • 簡単では ありませんでした - 簡単では なかった

友達

休みの日、散歩しなり 買い物に いったり します 

送別会

李さんは もう すぐ 来ると 思います・おも

見送り・み・おく

私は 新しい洋服が 欲しいです

形容词作动词使用,表示愿望。

  • 何が いちばん 欲しいですか?

表示 想干。。。 虽然前接动词,实际是形容词用法

  • 私は 映画を見たいです。 
  • 私は 映画を見たく ないです。
  • 何を したいですか? 
    •  何も したく ありません。
  • 誰に 会いたいですか? 
    •  誰にも 会いたく ないです。
  • どこへ 行きたいですか? 
    • どこへも 行きたく ないです。

疑问词+ でも = “什么都一样”

  • 何を 食べたい ですか? 
    •  何でも いいです。
  • 何時でも 電話を して ください。 
  • 誰でも 分かります。

初詣・はつもうで 

今年中に 結婚したいです。-ことし -けっこん 

携帯電話は とても 小さく なりました

形容词动词用法

  1. 变化  

    • パソコンは 安く なりました。 
    • もう 元気に なりました
    • 社会人に なりました
  2. 主语意志动作 形容词+します

    ジュースを 冷た く します

    テレビの音を 大きく します

    会議室を 禁煙に します

    部屋を きれい に して ください

  3. 两个性质对比 

    部屋は 広い ほんが いいです

    子供は 静かな ほんが いいです

新春セール 

お正月は 洋服が 安く なりますから、まとめて 買います。

どのぐらい 安く なりますか? 

だいたい 定価の3割引 か 半額に なります。・ていか・わりびき・がく 

私は 新しい洋服が ほしく なります。

部屋のかぎを 忘れない で ください。 

ない型的变化规律和使用场合

  • 一类动词变成 あ +ない ,如果是 い 时,变成 わ+ない

    • 買い -> 買わない
  • 二类动词直接加 ない

  • 三类动词  

    • きます -> こない 
    • します -> しない

ない 型表示否定式,祈使句,三种含义:不要,必须,也行**。**

  • 無理を しないで ください
  • すぐに 書類を 送ら なければ なりません
  • 明日は 残業し なくても いいですね

スキー

心配しないで ください。

スミスさんは ピアノを く ことが でかます・ひ

基本型

  • 一类动词  段 ,去掉 ます 发音为 
  • 二类动词 +
  • 三类动词  
    • きます->くる 
    • します->する 

基本型表示能力,行为习惯

  • 森さんは 中華料理を 作る ことが できますか? 
  • 森さんの夢は 外国を 働く こと です
  • こちらへ 来る前に、電話を かけて ください。

春節

机の上に 本が 三冊 あります

句子中插入成分:量词+時間+一个动作

  • はがきを 五枚 ください。-五枚で 二百五十円です。 
  • 李さんは 毎日 七時間 働きます。
  • 李さんは 一週間に 2回プールへ 行きます。
  • 新宿へ 映画を見に 行きました。
  • 午後 郵便局へ 荷物を出しに 行きます。
  • これから 森さんと 近くのお店へ 飲みに 行きます。

居酒屋

李さんは 一緒に どうですか?

昨日デパート いって、買い物しました

动词 て 型的变化规律和使用场景

い 段一类动词,会发生变音。

  • き行变音成いて,ち、り行变音成って,に、ひ、み行变音成 んで、し行不变音。

    | い | き | し | ち | に | ひ | み | り |
    | ——— | ——— | ———— | ——— | ——— | ——— | ——— | ——— |
    | 行き | 書き | 話し | 待ち | 死に | とび | 読み | 売り |
    | いって | かいて | はなして | まって | しんで | とんで | 読んで | 売って |

  • え 段二类动词,有少数 え 段二类动词,直接加 て。

  • 三类动词加来造词,也是直接加 て。

この道を まっすぐ 行って、橋を 渡って ください。

ここに 住所と名前を 書いて ください。

李さんは 毎晩 ラジオを 聞いてから 寝ます。

原稿・げんこう

小野さんは 今 新聞を 読んで います

て型的更多用法

1.现在进行

今 どこですか?

​ 今 市役所の前を 歩いて います。

2.请求和禁止

  • ここで 写真を とっても いいですか?

  • 教室で 物を 食べでは いけません

風邪

あまり 無理を しては いけません。

今 会議室で 打ち合わせを して います。後で 伝えます。-う・あ・あと・つた 

暖かい物を 食べて、十分 睡眠を とって ください。それから、今晩 お風呂に 入っては いけませんよ。

ホテルの部屋は 広くて 明るいです

形容词 て 型的运用。

  • この本は 安く おもしろいです。

  • 森さんは 親切 優しいです。 名词并列

展示場

单词

片假名

  • アルバム 
  • タバコ 
  • ガレージ 
  • ボーリンク 
  • メモ 
  • ボート 
  • ベンチ 
  • クーラー 
  • デザイン 
  • サービス 

生词

  • はがき 
  • 切手・きって
  • 引き出し・ひきだし
  • 焼き鳥・やきとり
  • 唐揚げ・からあげ
  • 肉じゃが
  • どのぐらい・どれぐらい 
  • 冊・さつ 杯・はい 匹・ひき 羽・わ 足・そく 皿・さら 
  • 船便・ふなびん 航空便・こうくう
  • 橋の角 はし・かど 
  • 横断歩道・おうだんほどう
  • 右・みぎ 左・ひだり 
  • 太極拳・たいきょくけん
  • 後で・あとで
  • お風呂・おふろ 
  • 打ち合わせ・うちあわせ 
  • 十分・じゅうぶん 
  • もちろん 
  • ゆっくり 
  • 製品・せいひん
  • 形・かたち
  • ネクタイ 
  • 緑・みどり 
  • 足・あし 指・ゆび め・目 鼻・はな 頭・あたま 顔・かお  
  • 間違い・まちがい 
  • 天井・てんじょう  
  • 警備・けいび 
  • 大切・たいせつ
  • 複雑・ふくざつ 
  • 頭がいい・あたま
  • 黒い・くろい ふとい 細い・ほそい 優しい・やさしい

动词

  • かかります 
  • 咲き・さき
  • 泳ぎます・およぎ
  • 遊びます・あそび
  • 切ります・きり
  • 通ります ・ とおり 
  • 急ぎます ・ いそぎ 
  • 飛びます ・ とび 
  • 死にます ・ しに 
  • 待ちます ・ まち
  • 売ります ・ うり 
  • 話し   ・ はなし 
  • 渡り   ・ わたり 
  • おろします・
  • 選び   ・ えらび 
  • 消し   ・ けし
  • 歩き   ・ あるき 
  • 曲がり  ・ ま 
  • 洗い   ・ あらい 
  • 出かけ  ・ でかけ
  • 過ぎます ・ すぎ 
  • 見せます ・ みせ 
  • あけ・つけ 
  • おります・
  • 卒業・そつぎょう 
  • 乗り・のり 
  • 使い・つかい 
  • 座り・すわり 
    • 入り・はいり 
    • 申します・もうし 
    • 取り・とり 
    • 伝え・つたえ 
    • 知ります・しり 
    • 持ちます・もち 
    • 直します・なおし
  1. 立入禁止 たち いり きん し
  2. 駐車禁止 ちゅうしゃ
  3. 進入禁止 しん にゆう
  4. 車両通行止 しゃりょう つう こう
  5. 右折禁止 う せつ
  6. 左折禁止 さ せつ
  7. 駐輪禁止 ちゅう りん 
  8. 一方通行 いち ぽん つう こう
  9. 止まれ と
  10. 禁煙 きんえん
  11. 火気厳禁 か き げん 
  12. 飲食禁止 いん しょく
  13. 使用禁止 し よう
  14. 遊泳禁止 ゆう えい
  15. 放送禁止 ほんそう
  16. 禁帯出 きん たい しゅつ
  17. 関係者以外 かん けい しゃ いがい