python进阶(20) 正则表达式的超详细使用
正则表达式
正则表达式(Regular Expression,在代码中常简写为regex、 regexp、RE 或re)是预先定义好的一个“规则字符率”,通过这个“规则字符串”可以匹配、查找和替换那些符合“规则”的文本。
虽然文本的查找和替換功能可通过字符串提供的方法实现,但是实现起来极为困难,而且运算效率也很低。而使用正则表达式实现这些功能会比较简单,而且效率很高,唯一的困难之处在于编写合适的正则表达式。
Python 中正则表达式应用非常广泛,如数据挖掘、数据分析、网络爬虫、输入有效性验证等,Python 也提供了利用正则表达式实现文本的匹配、查找和替换等操作的 re 模块。
1.1 正则表达式字符串
正则表达式是一种字符串,正则表达式字符串是由普通字符和元字符组成的。
1)普通字符
普通字符是按照字符字面意义表示的字符。
2)元字符
元字符是预先定义好的一些特定字符,比如\w、\.都属于元字符。
1.1.1 元字符
元字符(Metacharacters)是用来描述其他字符的特殊字符,它由基本元字符和普通字符构成。基本元字符是构成元字符的组成要素。基本元字符主要有14个,具体如下图所示。
| 字符 | 说明 |
|---|---|
| \ | 转义符,表示转义 |
| . | 表示任意一个字符 |
| + | 表示重复1次或多次 |
| * | 表示重复0次或多次 |
| ? | 表示重复0次或1次 |
| |
选择符号,表示“或关系”,例如:A | B 表示匹配A或B |
| {} | 定义量词 |
| [] | 定义字符类 |
| () | 定义分组 |
| ^ | 可以表示取反,或匹配一行的开始 |
| $ | 匹配一行的结束 |
上面表格中\w+ 是元字符,它由两个基本元字符(\和+)和一个普通字符 w构成。另外,还有.元字符,它由两个基本元字符\和,构成。
学习正则表达式某种意义上讲就是在学习元字符的使用,元字符是正则表达式的重点也是难点。下面会分门别类地介绍元字符的具体使用。
1.1.2 字符转义
在正则表达式中有时也需要字符转义,比如 w字符不表示英文字母 w,而是表示任何语言的单词字符(如英文字母、亚洲文字等)、数字和下画线等内容时,需要在w 字母前加上反斜杠\。反斜杠\也是基本元字符,与 Python 语言中的字符转义是类似的。不仅可以对普通字符进行转义,还可以对基本元字符进行转义。如上面的表格,其中点.字符是希望按照点.的字面意义使用,作为.com域名的一部分,而不是作为.基本元字符使用,所以需要加反斜杠\进行转义,即\.才是表示点.的字面意义。
1.1.3 开始与结束字符
本节通过一个示例介绍在 Python中如何使用正则表达式。
在1.1.1 节介绍基本元字符时介绍了^和$,它们可以用于匹配一行字符串的开始和结束。当以^开始时,要求一行字符串的开始位置匹配:当以$结束时,要求一行字符串的结位置匹配。所以正则表达式\w+@jiakecong.com和^w+@jiakecong.com$是不同的。
示例代码如下:
import re
p1 = r'\w+@jiakecong\.com'
p2 = r'^\w+@jiakecong\.com$'
text = "Tony 's email is tony_guan111@jiakecong.com"
m = re.search(p1, text)
print(m)
m = re.search(p2, text)
print(m)
email = "tony_guan111@jiakecong.com"
m = re.search(p2, email)
print(m)
输出结果如下:
<re.Match object; span=(17, 43), match='tony_guan111@jiakecong.com'>
None
<re.Match object; span=(0, 26), match='tony_guan111@jiakecong.com'>
1..2 字符类
在正则表达式中可以使用字符类,一个字符类定义一组字符,其中的任一一个字符出现在输入字符串中即匹配成功。注意每次匹配只能匹配字符类中的一个字符。
1.2.1 定义字符类
定义一个普通的字符类需要使用[和]元字符类。例如想在输入字符串中匹配Java或java,可以使用正则表达式[Jj]ava,示例代码如下:
p = r'[Jj]ava'
m = re.search(p, 'I like Java and Python')
print(m)
m = re.search(p, 'I like JAVA and Python')
print(m)
m = re.search(p, 'I like java and python')
print(m)
输出结果如下:
<re.Match object; span=(7, 11), match='Java'>
None
<re.Match object; span=(7, 11), match='java'>
上述代码中除了JAVA不匹配正则表达式[Jj]ava,其他都匹配
1.2.2 字符串取反
在正则表达式中指定不想出现的字符,可以在字符类前加^符号。示例代码如下:
import re
p = r'[^0123456789]'
m = re.search(p, '1000')
print(m)
m = re.search(p, 'python')
print(m)
上述代码定义的正则表达式[^0123456789],它表示输入字符串中出现非0-9数字即匹配,即出现在[0123456789]以外的任意一字符即匹配
1.2.3 区间
上面示例中的[^0123456789]正则表达式,事实上有些麻烦,这种连续的数字可以使用区间表示。区间是用连字符-表示的,例如[0123456789]采用区间表示为[0-9],[^0123456789]采用区间表示为[^0-9]。区间还可以表示连续的英文字母字符类,例如[a-z]表示所有小写字母字符类,[A-Z]表示所有大写字母字符类。
另外,也可以表示多个不同区间,[A-Za-z0-9]表示所有字母和数字字符类,[0-25-7]表示0、1、2、5、6、7几个字符组成的字符类。
示例代码如下:
import re
m = re.search('[A-Za-z0-9]', 'A10.3')
print(m)
m = re.search(r'[0-25-7]', 'A3489C')
print(m)
输出结果如下:
<re.Match object; span=(0, 1), match='A'>
None
1.2.4 预定义字符类
有些字符类很常用,例如[0-9]等。为了书写方便,正则表达式提供了预定义的字符类,例如预定义字符类\d等价于[0-9]字符类。预定义字符类如下图所示
| 字符 | 说明 |
|---|---|
| . | 匹配任意一个字符 |
| \ | 匹配反斜杠\字符 |
| \n | 匹配换行 |
| \r | 匹配回车 |
| \f | 匹配一个换页符 |
| \t | 匹配一个水平制表符 |
| \v | 匹配一个垂直制表符 |
| \s | 匹配一个空格符,等价于[\t\n\r\f\v] |
| \S | 匹配一个非空格符,等价于[^\s] |
| \d | 匹配一个数字字符,等价于[0-9] |
| \D | 匹配一个非数字字符,等价[^0-9] |
| \w | 匹配任意语言的单词字符、数字和下划线'_'等字符,如果正则表达式标志设置为ASCII,则只匹配[a-zA-Z0-9] |
| \W | 等价于[^\w] |
示例代码如下:
import re
p = r'\D'
m = re.search(p, 'assss')
print(m)
m = re.search(p, '1000')
print(m)
text = '你们好hello'
m = re.search(r'\w', text)
print(m)
输出结果如下:
<re.Match object; span=(0, 1), match='a'>
None
<re.Match object; span=(0, 1), match='你'>
上述代码正则表达式\D就等于[^0123456789]。另一个正则表达式\w表示任意字符,会在text字符串中查找匹配字符,找到的结果是你字符。
1.3 量词
之前学习的正则表达式元字符只能匹配显示一次字符或字符串,如果想匹配显示多次字符或字符串可以使用量词
1.3.1 量词的使用
量词表示字符或字符串重复的次数,正则表达式中的量词如下表:
| 字符 | 说明 |
|---|---|
| ? | 出现0或1次 |
| * | 出现0或多次 |
| + | 出现1或多次 |
| {n} | 出现n次 |
| {n,m} | 至少出现n次,但不超过m次 |
| {n,} | 至少出现n次 |
量词的使用示例代码如下:
import re
m = re.search(r'\d?', '87654321')
print(m)
m = re.search(r'\d?', 'ABC')
print(m)
m = re.search(r'\d*', '87654321')
print(m)
m = re.search(r'\d*', 'ABC')
print(m)
m = re.search(r'\d+', '87654321')
print(m)
m = re.search(r'\d+', 'ABC')
print(m)
m = re.search(r'\d{8}', '87654321')
print(m)
m = re.search(r'\d{8}', 'ABC')
print(m)
m = re.search(r'\d{7,8}', '87654321')
print(m)
m = re.search(r'\d{9, }', '87654321')
print(m)
输出结果如下:
<re.Match object; span=(0, 1), match='8'>
<re.Match object; span=(0, 0), match=''>
<re.Match object; span=(0, 8), match='87654321'>
<re.Match object; span=(0, 0), match=''>
<re.Match object; span=(0, 8), match='87654321'>
None
<re.Match object; span=(0, 8), match='87654321'>
None
<re.Match object; span=(0, 8), match='87654321'>
None
1.3.2 贪婪量词和懒惰量词
量词还可以细分为贪婪量词和懒惰量词,贪婪量词会尽可能多地匹配字符,懒惰量词会尽可能少地匹配字符。大多数计算机语言的正则表达式量词默认是贪婪的,要想使用懒惰量词在量词后面加?即可
示例代码如下:
import re
m = re.search(r'\d{5,8}', '87654321')
print(m)
m = re.search(r'\d{5,8}?', '87654321')
print(m)
输出结果如下:
<re.Match object; span=(0, 8), match='87654321'>
<re.Match object; span=(0, 5), match='87654'>
上述代码使用了贪婪量词{5,8},输入字符串87654321是长度8位的数字字符串,尽可能多地匹配字符结果是87654321。代码使用懒惰量词{5,8}?,输入字符串87654321是长度8位的数字字符串,尽可能少的匹配字符结果是87654。
1.4 分组
在此之前学习的量词只能重复显示一个字符,如果想让一个字符串作为整体使用量词,可将整个字符串放到一对小括号中,这就是分组(也称子表达式)
1.4.1 分组的使用
对正则表达式进行分组不经可以对一个字符串整体使用量词,还可以在正则表达式中引用已经存在的分组。示例代码如下:
import re
p = r'(121){2}'
m = re.search(p, '121121abcabc')
print(m)
print(m.group()) # 返回匹配的字符串
print(m.group(1)) # 返回第一组内容
p = r'(\d{3,4})-(\d{7,8})'
m = re.search(p, '010-87654321')
print(m)
print(m.group()) # 返回匹配字符串
print(m.groups()) # 获得所有组内容
输出结果如下:
<re.Match object; span=(0, 6), match='121121'>
121121
121
<re.Match object; span=(0, 12), match='010-87654321'>
010-87654321
('010', '87654321')
上述代码定义的正则表达式(121)是将121字符串分为一组,(121){2}表示对121重复两次,即121121。代码调用match对象的group()方法返回匹配的字符串,group()方法语法如下:
match.group([group1, ...])
其中参数group1是组编号,在正则表达式中组编号是从1开始的,所以代码正则表达式m.group(1)表示返回第一组内容
代码 r'(\d{3,4})-(\d{7,8})'正则表达式可以用来验证固定电话号码,在-之前是3-4位的区号,-之后是7-8位的电话号码。在该正则表达式中有两个分组。代码m.groups()方法是返回所有分组,返回值是一个元组
1.4.2 分组命名
在Python程序中访问分组时,除了可以通过组编号进行访问,还可以通过组名进行访问,前提是要在正则表达式中为组命名。组命名通过在组开头添加?P<分组名>实现。
示例代码如下:
import re
p = r'(?P<area_code>\d{3,4})-(?P<phone_code>\d{7,8})'
m = re.search(p, '010-87654321')
print(m)
print(m.group()) # 返回匹配字符串
print(m.groups()) # 获得所有组内容
# 通过组编号返回组内容
print(m.group(1))
print(m.group(2))
# 通过组名返回组内容
print(m.group('area_code'))
print(m.group('phone_code'))
输出结果如下:
<re.Match object; span=(0, 12), match='010-87654321'>
010-87654321
('010', '87654321')
010
87654321
010
87654321
上述代码其实和1.4.1的代码是一样的,只是给正则表达式命名了,以后就可以通过组编号或组名字来访问
1.4.3 反向引用分组
除了可以在程序diamante中访问正则表达式匹配之后的分组内容,还可以再正则表达式内部引用之前的分组。
下面通过示例熟悉以下反向引用分组。假设由于工作需要想解析一段XML代码,需要找到某一个开始标签和结束标签,示例代码如下:
import re
p = r'<([\w]+)>.*</([\w]+)>'
m = re.search(p, '<a>abc</a>')
print(m)
p = r'<([\w]+)>.*</([\w]+)>'
m = re.search(p, '<a>abc</b>')
print(m)
输出结果如下:
<re.Match object; span=(0, 10), match='<a>abc</a>'>
<re.Match object; span=(0, 10), match='<a>abc</b>'>
上述代码的正则表达式分成了两组,两组内容完全一样。但是测试结果发现他们都是匹配的,但是<a>abc</b>明显不是有效的XML代码,因为开始标签和结束标签应该是一致的。可见代码r'<([\w]+)>.*</([\w]+)>'并不能保证开始标签和结束标签是一致的。为了解决此问题,可以引用反向引用,即让第二组反向引用第一组。在正则表达式中反向引用语法是\组编号,组编号是从1开始的。示例代码如下:
import re
p = r'<([\w]+)>.*</\1>' # 使用了反向引用 ①
m = re.search(p, '<a>abc</a>')
print(m) # 匹配
m = re.search(p, '<a>abc</b>')
print(m) # 不匹配
输出结果如下:
<re.Match object; span=(0, 10), match='<a>abc</a>'>
None
上述代码第①行时定义正则表达式,其中\1是反向引用第一个组,从运行结果可见字符串<a>abc</a>是匹配的,而<a>abc</b>字符串不匹配
1.4.4 非捕获分组
前面介绍的分组称为捕获分组。捕获分组的匹配子表达式结果被暂时保存到内存中,以备表达式或其他程序引用,这个过程称为"捕获",捕获结果可以通过组编号或组名进行引用。但是有时并不想引用子表达式的匹配结果,不想捕获匹配结果,只是将小括号作为一个整体进行匹配,此时可以使用非捕获分组,在组开头使用?,可以实现非捕获分组
示例代码如下:
import re
s = 'img1.jpg,img2.jpg,img3.bmp'
# 捕获分组
p = r'\w+(\.jpg)'
mlist = re.findall(p, s) ①
print(mlist)
# 非捕获分组
p = r'\w+(?:\.jpg)'
mlist = re.findall(p, s) ②
print(mlist)
输出结果如下:
['.jpg', '.jpg']
['img1.jpg', 'img2.jpg']
上述代码实现了从字符串中查找.jpg结尾的文本,其中代码第①行和第②行的正则表达式区别在于前者是捕获分组,后者是非捕获分组。捕获分组将括号中的内容作为子表达式进行捕获匹配,将匹配的子表达式(即组的内容)返回,结果是['.jpg','.jpg']。而非捕获分组将括号中的内容作为普通的正则表达式字符串进行整体匹配,即找到.jpg结尾的文本,所以最后结果是['img1.jpg', 'img2.jpg']。
1.5 re模块
re是Python内置的正则表达式模块,前面虽然使用过re模块一些函数,但还有很多重要函数没有详细介绍,这一节将详细介绍这些函数
1.5.1 search()和match()函数
search()和match()函数非常相似,它们的区别如下所示
search():在输入字符串中查找,返回第一个匹配内容,如果找到一个则match对象,如果没有找到返回Nonematch():在输入字符串开始处查找匹配内容,如果找到一个则match对象,如果没有找到返回None
示例代码如下:
import re
p = r'\w+@jiakecong\.com'
text = "Tony 's email is tony_guan111@jiakecong.com" ①
m = re.search(p, text)
print(m)
m = re.match(p, text)
print(m)
email = 'tony_guan111@jiakecong.com' ②
m = re.search(p, email)
print(m)
m = re.match(p, email)
print(m)
# match对象几个方法
print('match对象几个方法:') ③
print(m.group())
print(m.start())
print(m.end())
print(m.span())
输出结果如下:
<re.Match object; span=(17, 43), match='tony_guan111@jiakecong.com'>
None
<re.Match object; span=(0, 26), match='tony_guan111@jiakecong.com'>
<re.Match object; span=(0, 26), match='tony_guan111@jiakecong.com'>
match对象几个方法:
tony_guan111@jiakecong.com
0
26
(0, 26)
上述代码第①行输入字符串开头不是email,search()函数可以匹配成功,而match()函数却匹配失败。代码第②行输入字符串开头就是email格式的邮箱,所以search()和match()函数都可以匹配成功
search和match()函数如果匹配成功都返回match对象。match对象有一些常用方法,见代码第③行。其中group()方法返回匹配的子字符串;start()方法返回子字符串的开始索引;end()方法返回子字符串的结束索引;span方法返回子字符串的跨度,它是一个二元素的元组。
1.5.2 findall()和finditer()函数
findall()和finditer()函数非常相似,它们的区别如下所示
- findall():在输入字符串中查找所有匹配内容,如果匹配成功,则返回
match列表对象,如果匹配失败则返回None - finditer():在输入字符串中查找所有匹配内容,如果匹配成功,则返回容纳
match的可迭代对象,通过迭代对象每次可以返回一个match对象,如果匹配失败则返回None
示例代码如下:
import re
p = r'[Jj]ava'
text = 'I like Java and java'
match_list = re.findall(p, text) ①
print(match_list)
match_iter = re.finditer(p, text) ②
for m in match_iter: ③
print(m.group())
输出结果如下:
['Java', 'java']
Java
java
上述代码第①行的findall()函数返回match列表对象。代码第②行的finditer()函数返回可迭代对象。代码第③行通过for循环遍历可迭代对象
1.5.3 字符串分割
字符串分割使用split函数,该函数按照匹配的子字符串进行字符串分割,返回字符串列表对象
re.split(pattern, string, maxsplit=0, flags=0)
其中参数pattern是正则表达式;参数string是要分割的字符串;参数maxsplit是最大分割次数,maxsplit默认值为零,表示分割次数没有限制;参数flags是编译标志
示例代码如下:
import re
p = r'\d+'
text = 'AB12CD34EF'
clist = re.split(p, text) ①
print(clist)
clist = re.split(p, text, maxsplit=1) ②
print(clist)
clist = re.split(p, text, maxsplit=2) ③
print(clist)
输出结果如下:
['AB', 'CD', 'EF']
['AB', 'CD34EF']
['AB', 'CD', 'EF']
上述代码调用split()函数通过数字对AB12CD34EF字符串进行分割,\d+正则表达式匹配一到多个数字。代码第①行split()函数中参数maxsplit和flags是默认的,分割的次数没有限制,分割结果是['AB', 'CD', 'EF']列表
代码第②行split()函数指定maxsplit为1,分割结果是['AB', 'CD34EF']列表,列表元素的个数是maxsplit+1。
代码第③行split()函数指定maxsplit为2,2是最大可能的分割次数,因此maxsplit≥2与maxsplit=0是一样的。
1.5.4 字符串替换
字符串替换使用sub()函数,该函数用于替换匹配的子字符串,返回值是替换之后的字符串。
re.sub(pattern, rep1, string, count=0, flags=0)
其中参数pattern是正则表达式;参数rep1是替换字符串;参数string是要提供的字符串;参数count是要替换的最大数量,默认值为零,表示替换数量没有限制;参数flags是编译标志
示例代码如下:
import re
p = r'\d+'
text = 'AB12CD34EF'
replace_text = re.sub(p, ' ', text) ①
print(replace_text)
replace_text = re.sub(p, ' ', text, count=1) ②
print(replace_text)
replace_text = re.sub(p, ' ', text, count=2) ③
print(replace_text)
输出结果如下:
AB CD EF
AB CD34EF
AB CD EF
上述代码调用sub()函数替换AB12CD34EF字符串中的数字。代码第①行sub()函数中参数count和flags都是默认的,替换的最大数量没有限制,替换结果是AB CD EF
代码第②行sub()函数指定count为1,替换结果是AB CD34EF
代码第③行sub()函数指定count为2,2是最大可能的替换次数,因此count≥2与count=0是一样的。
python进阶(20) 正则表达式的超详细使用的更多相关文章
- python进阶11 正则表达式
python进阶11 正则表达式 一.概念 #正则表达式主要解决什么问题? #1.判断一个字符串是否匹配给定的格式,判断用户提交的又想的格式是否正确 #2.从一个字符串中按指定格式提取信息,抓取页面中 ...
- Python 基础学习笔记(超详细版)
1.变量 python中变量很简单,不需要指定数据类型,直接使用等号定义就好.python变量里面存的是内存地址,也就是这个值存在内存里面的哪个地方,如果再把这个变量赋值给另一个变量,新的变量通过之前 ...
- JAVA 正则表达式 (超详细)
(PS:这篇文章为转载,我不喜欢转载的但我觉得这篇文章实在是超赞了,就转了过来,这篇可以说是学习JAVA正则表达的必读篇.作者是个正真有功力的人,阅读愉快) 在Sun的Java JDK 1.40版本中 ...
- 转载:JAVA 正则表达式 (超详细)
在Sun的JavaJDK 1.40版本中,Java自带了支持正则表达式的包,本文就抛砖引玉地介绍了如何使用Java.util.regex包. 可粗略估计一下,除了偶尔用Linux的外,其他Linu x ...
- python beautiful soup库的超详细用法
原文地址https://blog.csdn.net/love666666shen/article/details/77512353 参考文章https://cuiqingcai.com/1319.ht ...
- Python与Javascript相互调用超详细讲解(2022年1月最新)(三)基本原理Part 3 - 通过C/C++联通
目录 TL; DR python调javascript javascript调python 原理 基于Node.js的javascript调用python 从Node调用python函数 V8 嵌入P ...
- Python与Javascript相互调用超详细讲解(四)使用PyNode进行Python与Node.js相互调用项(cai)目(keng)实(jing)践(yan)
目录 前提 安装 使用 const pynode = require('@fridgerator/pynode')的时候动态链接错误 ImportError: math.cpython-39-x86_ ...
- python进阶之正则表达式
概念: 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑. 目的? 给定一个正则表 ...
- Python与Javascript相互调用超详细讲解(2022年1月最新)(一)基本原理 Part 1 - 通过子进程和进程间通信(IPC)
TL; DR 适用于: python和javascript的runtime(基本特指cpython[不是cython!]和Node.js)都装好了 副语言用了一些复杂的包(例如python用了nump ...
随机推荐
- 42 张图带你撸完 MySQL 优化
Hey guys,这里是程序员cxuan,欢迎你阅读我最新一期的文章,这篇文章是 MySQL 调优的汇总版,我加了一下日常开发过程中的调优经验,希望对各位小伙伴们有所帮助.下面开始正文. 一般传统互联 ...
- CSP-S 2020
游记 Day# 游记个鬼啊就在自家学校=-= 早上宿舍待不了,去机房颓废,看了几集猫和老鼠,并且把看门狗军团的流程看完了(真棒),甚至在考试之前把老师给的巧克力也吃完了. 期间zyt学长来摸鱼.他们今 ...
- 【洛谷1339 [USACO09OCT]】热浪Heat Wave 图论+最短路
AC代码 #include<bits/stdc++.h> using namespace std; const int MAXN=62000+10,INF=999999; struct E ...
- etcd学习(4)-centos7中部署etcd
etcd的搭建 前言 单机 集群 创建etcd配置文件 更新etcd系统默认配置 启动 配置ETCD为启动服务 测试下 参考 etcd的搭建 前言 这里记录下如何搭建etcd 单机 在etcd的rel ...
- Windows7/10 防火墙开放Oracle数据库1521端口
安装Oracle 12C数据库,在局域网中,允许其他电脑访问,则需要开启防火墙的 1521端口 ==================================================== ...
- windows 10家庭版安装SQL Server 2014出现.net 3.5失败问题解决。
在安装SQL Server 2014的过程中,出现.net 3.5缺失,导致失败问题. 后来,研究了下,解决思路如下: 先将电脑更新到了windows 10专业版,(因为需要用到专业版才有的组策略管理 ...
- noip模拟测试10
T1 这道题在考场上想到了二维前缀和,就是自己算前缀和的方式有点麻烦,导致花的时间较长,但还是成功搞了出来. 因为暴力计算的话需要不停枚举左上角和右下角的 i ,j, 时间复杂度为 n^4 ,我当时就 ...
- SpringCloud升级之路2020.0.x版-6.微服务特性相关的依赖说明
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford spring-cl ...
- 涨姿势啦!Java程序员装X必备词汇之对象标记Mark Word!
大家好,我是庆哥Java,一个专注于干货分享的Java自学者! 写在前面 如果你已经知道什么是Mark Word,那我也希望你都好好阅读下本篇文章,因为你有可能发现不一样的切入点来帮助你更加深入的了解 ...
- 『Java』List Set
观前提醒:本文内容多为入门时的学习笔记,笔记内容有些混乱!!! | | | | | | | | | | | | 泛型只能是引用类型,不能是基本类型. 如果希望集合中存储的是基本类型数据,需要基本类型对 ...