regular expression - 正则表达式 - REGEX
- Pattern — 适用于完成筛选和过滤的操作
- 指定规则进行范围性/模糊匹配
- 在正则中用()将某一块作为一个整体来操作 — 捕获组
- Java中的正则会对其中的捕获组进行编号,从1开始 — 从 ( 开始计算
package cn.tedu.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PatternDemo1 {
public static void main(String[] args) {
String str = "abc";
// 判断字符串是否是abc
// System.out.println(str.equals("abc"));
// 编译正则规则形式
// Pattern p = Pattern.compile("abc");
// 将正则进行匹配
// Matcher m = p.matcher(str);
// 进行判断
// boolean b = m.matches();
// 判断字符串:
// 由3个字母组成
// 第一个字母是a/b/c
// 第二个字母是d/e/f/g
// 第三个字母是x/y/z
Pattern p = Pattern.compile("[bac][gedf][xyz]");
Matcher m = p.matcher(str);
boolean b = m.matches();
System.out.println(b);
}
}
String类的matches方法的底层用的就是上面的代码
目录,再往上一拉
// 判断字符串:
// 由3个字母组成
// 第一个字母是a/b/c
// 第二个字母是d/e/f/g
// 第三个字母是x/y/z
// System.out.println(str.matches("[abc][defg][xyz]"));
// 匹配由一个字母组成的字符串
// System.out.println(str.matches("[a-zA-Z]"));
// 匹配由一个数字组成的字符串
// System.out.println(str.matches("[0-9]"));
// System.out.println(str.matches("\\d"));
// 匹配由一个字符组成的字符串,但不是a/b/c
// [^...] 表示除了这些字符
System.out.println(str.matches("[^abc]"));
// 匹配由a开头的由2个字符组成的字符串
// . 表示通配符,可以匹配任意一个类型的字符
// System.out.println(str.matches("a."));
// 判断是否是一个 .
// \\. Java先转义为\. ,正则再转义为.
// System.out.println(str.matches("\\."));
// 怎么匹配 \
// \\\\ Java先转义为\\ ,正则再转义为\
System.out.println(str.matches("\\\\"));
// 数量词
// 匹配由a开头至少由2个字符组成的字符串
// System.out.println(str.startsWith("a") && str.length() >= 2);
// + 表示之前的字符至少出现1次 >= 1
// System.out.println(str.matches("a.+"));
// 匹配由小写字母开头由数字结尾的字符串
// * 表示之前的字符(一位)可有可无 >= 0 * 只是数量概念,即数量修饰符。
// . 表示数据类型,它是通配符,可以表示任意类型。
// .*表示这些位的数据类型是. 个数用*表示,>= 0 的。
// System.out.println(str.matches("[a-z].*\\d"));
// 匹配由a开头至多2个字符组成的字符串
// ? 表示之前的字符至多出现1次 <= 1
System.out.println(str.matches("a.?"));
// 匹配由5个小写字母组成的字符串
// {n} 表示之前的字符恰好出现n次 == n
// System.out.println(str.matches("[a-z]{5}"));
// 匹配至少由5个小写字母组成的字符串
// System.out.println(str.matches("[a-z]{5,}"));
// 匹配由8-12个小写字母组成的字符串
System.out.println(str.matches("[a-z]{8,12}"));
// String str = "fabtab";
// 判断含有至少2个ab的字符串
// () 捕获组
// 正则表达式会对其中的捕获组进行自动的编号
// 编号是从1开始的
// System.out.println(str.matches(".*(ab).*(ab).*"));
// \\n 表示引用前边编号为n的捕获组
// System.out.println(str.matches(".*(ab).*\\1.*"));
// 捕获组的编号是从捕获组的左半边括号出现的位置开始计算的
// (A((BC)(D))E)(F)
// \\1 A((BC)(D))E
// \\2 (BC)(D)
// \\3 BC
// \\4 D
// \\5 F
// 判断一个字符串是否是一个叠字字符串
// 哈哈哈 啊啊啊啊
// String str = "笑哈哈";
// System.out.println(str.matches("哈{2,}"));
// System.out.println(str.matches("(.)\\1+"));
// 表示匹配由至少2个字符组成的字符串
// System.out.println(str.matches("(.){2,}"));
// 匹配AABB形式的词语
// 欢欢喜喜
// String str = "上上下下";
// System.out.println(str.matches("(.)\\1(.)\\2"));
// 匹配ABAB形式的词语
// 休息休息 溜达溜达
String str = "休息休息";
System.out.println(str.matches("(..)\\1"));
// String str = "va87gg[bq;903h/0gvd'sga9gsd";
// System.out.println(str.replace('0', '-'));
// 将所有的数字替换为-
// System.out.println(str.replaceAll("\\d", "-"));
// 将所有非数字全部去掉
// System.out.println(str.replaceAll("\\D", ""));
// String str = "Cat Dog Pig Mouse Snake";
// 交换Dog和Snake的顺序
// 在replaceAll中可以$n的形式引用前一个正则中对应编号的捕获组
// System.out.println(str.replaceAll("(Cat )(Dog)( Pig Mouse )(Snake)",
// "$1$4$3$2"));
String str = "我我我我我我我我爱爱爱爱学学学习习习习习习习习习习习";
// 我爱学习
System.out.println(str.replaceAll("(.)\\1+", "$1"));
// 以数字作为切割符将字符串切开
// 作为切割符的符号会被切掉
// 在字符串最末尾的切割符会被整个切掉
// 除了在末尾的切割符以外,最前面也可以和其余的相邻的切割符之间也会切出一个空字符串。
// 把切割符替换成逗号就行
String[] strs = str.split("\\d");
System.out.println(strs.length);
System.out.println(Arrays.toString(strs));
练习:
目录,再往上一拉
输入一个字符串,然后判断字符串是否是一个小数字符串
System.out.println(str.matches("0\\.\\d+") || str.matches("[1-9]\\d*\\.\\d+"));
校验密码:8-20位,小写字母/大写字母/数字中的至少两种
package cn.tedu.regex;
public class PatternExer2 {
public static void main(String[] args) {
String pwd = "";
System.out.println(check(pwd));
}
private static boolean check(String pwd) {
if (!pwd.matches("[a-zA-z0-9]{8,20}"))
return false;
// 记录出现的字符的种类
int count = 0;
// 判断是否含有小写字母
if (pwd.matches(".*[a-z].*"))
count++;
// 判断是否含有大写字母
if (pwd.matches(".*[A-Z].*"))
count++;
// 判断是否含有数字
if (pwd.matches(".*\\d.*"))
count++;
return count >= 2;
}
}
- 邮箱格式的校验:
2607509766@qq.com langang@163.com
langang@tedu.cn langang@sina.com.cn
String email = "";
System.out.println(email.matches("[a-zA-Z0-9]{6,32}@[a-zA-Z0-9]+(\\.com)")
|| email.matches("[a-zA-Z0-9]{6,32}@[a-zA-Z0-9]+(\\.com)?(\\.cn)"));
}
目录,再往上一拉
2. 输入一个字符串,统计其中每一个字符出现的次数
package cn.tedu.regex;
import java.util.Scanner;
public class PatternExer2 {
@SuppressWarnings("resource")
public static void main(String[] args) {
// 获取字符串
Scanner s = new Scanner(System.in);
String str = s.next();
while (str.length() > 0) {
// 获取字符串的第一个字符
char c = str.charAt(0);
// 记录字符串的原长度
int len = str.length();
// 替换掉所有和第一个字符相同的字符
str = str.replaceAll("" + c, "");
// 计算替换掉的字符的个数
// 替换掉几个字符,字符串的长度就会变化几位
// 所以字符串的长度之差就是替换掉的字符的个数
System.out.println(c + ":" + (len - str.length()));
}
}
}
目录,再往上一拉
3. 对于任意的字符串可以认为是由多组叠字或者是单字来拼成的,这每一组叠字/单字都是字符串的碎片,计算一个字符串平均的碎片长度
aaabbbbbcddaaacc -> aaa bbbbb c dd aaa cc -> (3 + 5 + 1 + 2 + 3 + 2) / 6 = 2.67
package cn.tedu.regex;
import java.util.Scanner;
public class PatternExer3 {
@SuppressWarnings("resource")
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String str = s.next();
// 记录字符串的原长度 --- 碎片的总长度
double len = str.length();
// 将字符串中所有的叠字替换为单字
str = str.replaceAll("(.)\\1+", "$1");
// 替换之后的长度就是碎片的个数
// 计算碎片的平均长度
System.out.println(len / str.length());
}
}
包装类
- 基本类型身上没有属性和方法来便捷的操作数据,因此针对每一种基本类型提供了对应的类形式 — 包装类
- Void是最终类,不能被实例化
- 当把基本类型的变量直接赋值给对应的引用类型的对象 — 自动封箱,底层是调用了对应类身上的valueOf方法
- 当把引用类型的对象直接赋值给对应的基本类型的变量 — 自动拆箱,底层是调用了对应对象身上的**Value方法
- 四种整数型都有范围判断(-128~127)
- 注意:凡是Number的子类都会提供将字符串转化为对应类型的构造方法
- 自动封箱/拆箱都是JDK1.5的特性之一。
- 包装类的对象的实际值只要相同则它的哈希码就一定是相同的。
- 包装类产生的对象的哈希码是固定的,不随环境改变
- 注意:字面量的哈希码是不随环境不随系统而改变
https://blog.csdn.net/realwongp/article/details/88901418
// 如果返回值类型定义为Void,返回值必须定义为null
public Void m2(){
System.out.println("hello m2~~~");
return null;
}
目录,再往上一拉
注意:凡是Number的子类都会提供将字符串转化为对应类型的构造方法
Integer in = new Integer("-284");
System.out.println(in);
int i = Integer.parseInt("259");
System.out.println(i);
Double dou = new Double("3.954");
System.out.println(dou);
// 不考虑大小写的情况只要不是true那么就是false
Boolean b = new Boolean("true");
System.out.println(b);
// NaN是唯一的一个值
// NaN与任何东西都不相等,包括自己本身
// System.out.println(Double.NaN == Double.NaN);
System.out.println(Double.isNaN(Double.NaN));
// Integer i1 = Integer.valueOf
// 如果值不在-128~127范围内
// 底层的valueOf方法是调用了构造方法来返回一个新的对象
// 如果值在-128~127的范围内的时候
// 从cache数组中的对应下标位置上取值
Integer i1 = -125;
Integer i2 = -125;
System.out.println(i1 == i2);
Integer in = 400;
int i = 400;
// 当包装类和对应的基本类型在运算的时候会进行自动拆箱
System.out.println(in == i);
数学类
目录,再往上一拉
Math — 最终类,针对基本类型提供了基本的初等数学运算
BigDecimal — 能够精确运算小数,要求参数以字符串形式传递
DecimalFormat — 进行数字的格式化的类
BigInteger:用于运算任意大的整数,要求整数以字符串或者是对应的补码的字节数组形式来传递。
// 计算任意大的整数
// 需要将过大的整数以字符串形式传入
BigInteger bi1 = new BigInteger("434168613543100552413456315463146318879641674641764198746796896841687984");
BigInteger bi2 = new BigInteger("796846341659846316874684149874613496743135796413414684163749684634116874");
System.out.println(bi1.multiply(bi2));
package cn.tedu.math;
import java.math.BigDecimal;
public class BigDecimalDemo {
// 原来在程序中是以64位二进制来计算小数
// strictfp要求方法在计算过程中以80位二进制来计算小数
// 但是计算完成之后仍然要求结果以64位二进制来进行存储
public strictfp static void main(String[] args) {
// 十进制小数转化为二进制的时候本身就不精确
double d1 = 3.54;
double d2 = 2.989;
System.out.println(d1 - d2);
// 如果想要精确运算,需要将参数以字符串形式传递
BigDecimal bd1 = new BigDecimal("3.546564");
BigDecimal bd2 = new BigDecimal("2.989347");
System.out.println(bd1.subtract(bd2));
}
}
package cn.tedu.math;
import java.math.RoundingMode;
import java.text.DecimalFormat;
public class DecimalFormatDemo {
public static void main(String[] args) {
// double price = 10.00;
// double real = price * 0.95;
// 0 表示一位数字,如果这一位上没有计算出数字来,那么会默认以0作为填充
// # 表示这一位上如果有数字则填充,如果没有数字则不填充
// DecimalFormat df = new DecimalFormat("#0.00");
// DecimalFormat df = new DecimalFormat("00.00");
// String str = df.format(real);
long l = 46108431746L;
// 将这个值转化为科学计数法形式
DecimalFormat df = new DecimalFormat("0.##E0");
// 设置近似模式
df.setRoundingMode(RoundingMode.CEILING);
String str = df.format(l);
System.out.println(str);
}
}
package cn.tedu.math;
//import java.util.Random;
public class MathDemo {
public static void main(String[] args) {
// 获取绝对值
// System.out.println(Math.abs(-5.86));
// 求立方根
// System.out.println(Math.cbrt(27));
// 向上取整
// System.out.println(Math.ceil(4.06));
// 乡下取整
// System.out.println(Math.floor(8.95));
// 四舍五入
// System.out.println(Math.round(3.68));
// 返回一个[0,1)的随机小数
// System.out.println(Math.random());
// 获取30-90之间的随机整数
// int i = (int) (Math.random() * 61 + 30);
// System.out.println(i);
// 表示获取0-30之间的随机整数
// Random r = new Random();
// System.out.println(r.nextInt(30));
// 0.15%
for (int i = 0; i < 10000; i++)
if (Math.random() * Math.random() > 0.95)
System.out.println("亲,恭喜您,中奖了~~~");
}
}
日期类
Date — 重点掌握字符串和日期之间的转换 — SimpleDateFormat
Calendar — 抽象类
SimpleDateFormat:parse将字符串转化为日期,format将日期转化为字符串。
Calendar:表示日历的类。从JDK1.2开始,Java推荐使用Calendar
// 将字符串转化为日期
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
// Date date = sdf.parse("2000.12.15 18:58:45");
// 将日期转化为字符串
// XX年XX月XX日
// XX时XX分XX秒
// SimpleDateFormat sdf2 = new SimpleDateFormat("yy年MM月dd日\r\nHH时mm分ss秒");
// String str = sdf2.format(date);
// System.out.println(str);
// 获取当前的系统时间
// Date date = new Date();
// 这个方法在1900-01的基础上来进行累加
// @SuppressWarnings("deprecation")
// 这个方法已过时
// 已过时指当前方法可以使用但是不推荐使用,在后续版本中可能会随时抛弃
// Date date = new Date(2000, 2, 9);
// Date date = new Date(2000 - 1900, 2 - 1, 9);
// System.out.println(date);
Calendar c = Calendar.getInstance();
// System.out.println(c);
时间包
在JDK1.8中对时间体系进行了全新的详细的划分,划分出来一个详细的时间体系的包 — java.time
package cn.tedu.time;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class LocalDateDemo {
public static void main(String[] args) {
// LocalDate是一个只包含日期而不包含时间的类
// 获取当前系统的日期
// LocalDate date = LocalDate.now();
// 指定日期
LocalDate date = LocalDate.of(2016, 5, 9);
System.out.println(date.plus(7, ChronoUnit.WEEKS));
System.out.println(date.minus(8, ChronoUnit.MONTHS));
// System.out.println(date.getDayOfWeek());
// System.out.println(date.getDayOfYear());
// System.out.println(date);
// System.out.println(date.isAfter(LocalDate.now()));
// 判断闰年
// System.out.println(date.isLeapYear());
// 只含有时间而不含有日期
// LocalTime time = LocalTime.now();
LocalTime time = LocalTime.of(15, 59, 37, 4616);
System.out.println(time);
}
}
小知识点
构造 匹配
字符类
[abc] a、b 或 c(简单类)
[^abc] 任何字符,除了 a、b 或 c(否定)
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)
[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集)
[a-z&&[def]] d、e 或 f(交集)
[a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去)
[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去)
预定义字符类
. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
边界匹配器
^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾
Greedy 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次