1.单例模式
- 单例模式: 保证类的实例只有一个。
- 构造函数私有化,提供一个可以获取到对象的静态公开方法。
- 方式1
// 单例模式
public class Singleton {
// 自己创建一个对象
private static Singleton s = new Singleton();
// 提供一个私有构造函数
private Singleton() {
}
// Instance : 实例化
// synchronized: 同步 (保证这个方法被线程使用完之后, 其他线程才可以使用到。)
public static synchronized Singleton getInstance() {
return s;
}
}
class Test1 {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
// 判断是否为同一个对象
System.out.println(s1 == s2);
}
}
- 方式2
//单例模式
public class SingletonA {
// 定义一个静态变量
private static SingletonA sa;
// 私有化构造函数
private SingletonA() {
}
//提供一个静态函数
public static synchronized SingletonA getInstance() {
if (sa == null) {
sa = new SingletonA();
}
return sa;
}
}
- 单例:
- 非单例:一个类型可以创造出多个对象
- 用单例模式写一个冒泡排序算法(面试题)
- 知识点1:单例模式
public class Singleton {
//提供一个是私有构造函数
private Singleton(){}
//自己创建一个对象
private static Singleton s = new Singleton();
//Instance : 实例化
public static synchronized Singleton getSingleton(){
return s;
}
public int[] sort(int[] arr){
for(int i = 0; i < arr.length -1 ; i++){
for (int j = 0; j < arr.length-1-i; j++){
if (arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
return arr;
}
}
class Test1{
public static void main(String[] args) {
Singleton s1 = Singleton.getSingleton();
Singleton s2 = Singleton.getSingleton();
System.out.println(s1 == s2);
Singleton s = Singleton.getSingleton();
int[] arr = {5,4,3,2,1};
System.out.println("排序后的数组"+ Arrays.toString(s.sort(arr)));
}
}
- 知识点2: 冒泡排序
public class SingletonA {
//定义一个静态变量
private static SingletonA sa;
//私有化构造函数
private SingletonA() {
}
//提供一个静态函数
public static synchronized SingletonA getSingleton() {
if (sa == null) {
sa = new SingletonA(); // 保证只执行一次。
}
return sa;
}
public int[] sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
}
class Test2 {
public static void main(String[] args) {
SingletonA s = SingletonA.getSingleton();
int[] arr = {5, 4, 3, 2, 1};
System.out.println("排序后的数组" + Arrays.toString(s.sort(arr)));
}
}
2.String类中的方法使用
- 查找指定字符串在某字符串中的索引位置
//字符串的方法
//--- 跟索引有关
public class StringDemo1 {
public static void main(String[] args) {
String str = "abtomcdtomeftomastomdftom"; // "tom"是一个子字符串
//1.找到字符串tom
//字符串.indexOf(字串) -- 找到某个字符串在原字符串的位置
// *** 找到就返回这个字符串的首字符位置,找不到就返回-1
/*int i = str.indexOf("tom1");
System.out.println(i);
if (i == -1){
System.out.println("找不到");
}*/
// 2. 从指定位置开始找
//int i1 = str.indexOf("tom", 3);
//System.out.println(i1);
//3.统计“tom”的个数
int count = 0;
int index = str.indexOf("tom"); //先找到第一个tom
if (index != -1) {
count++;
index = index + 3; //找到第一个后,往后找
}
while (index != -1) {
index = str.indexOf("tom", index); //继续往后找tom
if (index != -1) {
count++;
index = index + 3; //下一次寻找的起点
}
}
System.out.println("tom有" + count + "个");
//3.lastIndecOf(字符串) -- 从后往前找,找到最后一个出现的字符串的索引位置
System.out.println(str.lastIndexOf("tom")); //
//3.lastIndecOf(字符串, index)
System.out.println(str.lastIndexOf("tom", 6));
System.out.println(str.lastIndexOf("tom1")); // -1
//计算出"aaaa33aaa22233" -- a的个数
char c = str.charAt(0);
if (c == 'a') {
System.out.println("个数加1");
}
}
}
- 截取子字符串
//-- 子字符串
public class StringDemo2 {
public static void main(String[] args) {
String s = "tomjackalicerose"; // 每个字符有一个对应的索引位置
// 1.获取字字符串
//找到tom
//substring(begin) --- 指定开始位置,到字符串结尾的子字符串
//substring(begin, end) -- 从指定位置开始,到end-1位置结束的字符串。 [begin,end) -- 包含前面,不包含后面
//Math.random() [0,1) -- 包含0,不包含1
String sub1 = s.substring(0, 3);
System.out.println(sub1);
s.substring(s.indexOf("rose"));
System.out.println(sub1);
//2.练习:字符串 。。。,找到邮箱名字
String email = "rose@qq.com";
sub1 = email.substring(0,email.indexOf("@")); //
System.out.println("邮箱名字为:"+sub1);
System.out.println(email.substring(0, email.lastIndexOf("@")));
System.out.println(email.substring(email.indexOf("@") + 1));
//3。练习:把字符串str 按三个一组,截取为子字符串,然后保存遭字符数组中
String str = "abcdefghijklmn";
String[] ss = new String[0];
}
}
字节数组 & 字符编码
public class StringDemo3 {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "中国你好";
byte[] bytes = str.getBytes(); // 没有指定编码,就看当前软甲使用的编码方式
System.out.println(Arrays.toString(bytes) +"-------"+bytes.length);
byte[] bytes1 = str.getBytes("utf-8"); //一个中文字符三个字节
byte[] gbks = str.getBytes("gbk"); //一个中文两个字符
System.out.println(Arrays.toString(bytes1) +"-------"+bytes1.length);
System.out.println(Arrays.toString(gbks) +"-------"+gbks.length);
byte[] bytes2 = str.getBytes(StandardCharsets.UTF_8); // StandardCharsets.UTF_8 -- 常量
//字符串的构造函数
String str1 = new String("hello");
String str2 = new String(gbks); // gbks中存的gbk编码获取的字节数组,类使用的utf-8编码。
str2 = new String(gbks, "gbk");
System.out.println(str2); // 乱码?
char[] c = {'a', 'b', 'c'};
String str3 = new String((c));
System.out.println(str3);
}
}
3.正则表达式
3.1 正则表达式的介绍
-
正则表达式是一个特殊的字符串,是由一些特定的字符串组成的“规则字符串”。
-
正则表达式,主要用于对字符串进行匹配,查找,替换等操作。
比如: 如果检查一个字符串是否符合邮箱的规则。
名字 @ qq . com
/1+@[a-zA-Z0-9]+(.[a-zA-Z0-9]+)+$/
(.[a-zA-Z0-9]+)称为一个组
-
正则表达式的规则**:**
- 可以出现的字符
- 可以出现的字符简写
- 字符串出现的次数限定
- 其他规定
3.2 String中正则表达式的使用
- split方法把字符串按照指定的分隔符,分割为字符串数组。
- String提供了用于字符串替换的方法
-
代码:
-
split: 字符串切割位数组
-
replaceAll:把正则匹配的内容,替换为指定的字符串
-
//split方法的使用
//regex : 正则, ① 能出现的哪些字符,②出现的次数,③特殊规定:限定开始,限定结尾,全局查找,忽略大小写。
public class StringDemo4 {
public static void main(String[] args) {
//1.根据数字,把字符串切割为字符串数组
String str = "aa12321bb3434cc1dd343ee33"; // {"aa","bb","cc","dd","ee"}
String regex = "[0-9]{1,}";
//split --- 分割, split(regex) --- 根据正则表达式的匹配规则,把字符串,分割为字符串数组
String[] split = str.split(regex);
System.out.println(Arrays.toString(split));
//按字母来切割,得到字符串数组
regex = "[a-z]{1,}";
split = str.split(regex);
System.out.println(Arrays.toString(split));
//2.练习 2023.8.3 转为2023-8-3
String year = "2023.8.3";
regex = "\\."; // 正则中的"."表示任意字符,使用"\."表示点本身
String[] ys = year.split(regex);
System.out.println(ys[0] + "-" + ys[1] + "-" + ys[2]);
//3.练习:0123456789 ,变成0-1-2-3-4-5-6-7-8-9
String old = "0123456789";
regex = "";
String[] ds = old.split(regex);
String dStr = "";
for(int i = 0; i < ds.length; i++){
dStr += ds[i] + "-";
}
System.out.println(dStr);// 0-1-2-3-4-5-6-7-8-9-
String subStr = dStr.substring(0,dStr.length()-1);
System.out.println(subStr);// 0-1-2-3-4-5-6-7-8-9
//4. 思考: “abtomcdtomefto1tom2tom” 把tom 替换为TOM
regex = "tom";
old = "abtomcdtomefto1tom2tom";
ds = old.split(regex);
System.out.println("ds:" + Arrays.toString(ds));
//5.使用replaceAll(正则,字符串) --- 把正则匹配的内容,替换为指定的字符串
String s = old.replaceAll("tom", "TOM");
System.out.println(s);
System.out.println(year.replaceAll("\\.", "/"));
//6.练习"中国你好";---把你好,替换为"是我最喜欢的国家"。
old = "中国你好";
String newStr = old.replace("你好", "是我最喜欢的国家");
System.out.println(newStr);
//7.练习: “你妈最近身体好吗,你妹妹最近考上那个大学.我最喜欢的明星范冰冰,我妈妈也喜欢,因为演技很好。”,把妈显示为**
old = "你妈最近身体好吗,你妹妹最近考上那个大学.我最喜欢的明星范冰冰,我妈妈也喜欢,因为演技很好。";
newStr = old.replaceAll("妈{1,}|妹{1,}|[冰]+","******");
System.out.println(newStr);
}
}
4.StringBuffer & StringBuilder
4.1 StringBuffer
-
StringBuffer封装可变的字符串, StringBuffer对象创建后,可以通过调用方法,修改字符串的内容。
-
StringBuffer构造器函数
-
public StringBuffer();
-
public StringBuffer(String str);
-
-
StringBuffer提供的操作字符串的方法: append , insert , delete , replace,reverse等。
-
StringBuffer提供的很多方法,返回值是StringBuffer(return this ) , 所以支持链式操作:
StringBuffersb = new StringBuffer(“a”);
sb.append(“b”).append(“b”)…
4.2 StringBuilder
-
StringBuilder封装可变的字符串, StringBuilder对象创建后,可以通过调用方法,修改字符串的
内容。
-
StringBuilder构造器函数
public StringBuilder();
public StringBuilder(String str);
-
StringBuilder提供的操作字符串的方法: append , insert , delete , replace,reverse等。
-
StringBuilder提供的很多方法,返回值是StringBuilder (return this ) , 所以支持链式操作:
StringBuilder sb = new StringBuilder(“a”);
sb.append(“b”).append(“b”)…
4.3 参考代码
- 把类型修改为StringBuffer ,以下方法均可正常使用。
//StringBuilder 中提供的方法
public class StringBuilderDemo1 {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
//追加 -- append
sb.append("今天天气很好。");
System.out.println(sb);
//插入 -- insert
sb.insert(2,"是星期四"); // 指定位置之前插入
System.out.println(sb.toString()); //输出对象本身就是在调用toString方法。
//替换 -- replace
int begin = sb.indexOf("星期四");
int end = begin + "星期四".length();
sb.replace(begin, end, "XQS");
System.out.println(sb);
//删除 -- delete
begin = sb.indexOf("是XQS");
end = begin + "是XQS".length();
sb.delete(begin, end);
System.out.println(sb);
//反转 -- reverse
sb.reverse();
System.out.println(sb);
//练习: 判断"上海自来水来自海上"是不是回文。
String str = "上海自来水来自海上";
StringBuilder sb1 = new StringBuilder(str);
sb1.reverse();
if (str.equals(sb1.toString())) {
System.out.println("是回文");
}else{
System.out.println("不是回文");
}
}
}
4.4 如果频繁修改字符串,使用StringBuilder/StringBuffer
4.5 String , StringBuffer ,StringBuilder的区别
-
String vs StringBuffer vs StringBuilder
-
StringBuffer和StringBuilder类提供了操作字符串的方法。
-
String是不可变的,StringBuffer和StringBuilder是可变的。
-
-
String类的特点:
- String类是不可变的,一旦创建就不能被修改。
- 在多线程环境下是安全的,因为它是不可变的。
- 在字符串池中使用相同的字符串来节省内存。
-
StringBuffer的特点:
- 在Java1.4之前,StringBuffer是唯一的字符串操作类。
- 所有的public方法都是同步的,适合在多线程环境下使用。
- 提供线程安全,但性能相对较低。
-
StringBuilder的特点:
- 自Java1.5开始引入,用于取代StringBuffer,性能更好。
- 所有的public都不是同步的,适合单线程环境下使用。
- 没有StringBuffer的一些额外方法,因为这些方法在String中已经存在。
-
StringBuffer和StringBuilder的相似之处:
- StringBuffer和StringBuilder都是可变的,适用字符串拼接和修改。
- 他们提供了append()、insert()、delete()、substring()等方法来来操作字符串。
5. 字符串操作练习:
import java.util.Scanner;
public class Home {
public static String fetch(String str) {
//封装一个方法, 把字符串的从右边开始的第4到第七位取出来
StringBuilder sb = new StringBuilder(str);
sb.reverse(); // 反转
return sb.substring(3, 7); //返回子字符串
}
public static void main(String[] args) {
String str1 = "12345678";
System.out.println(fetch(str1));
//输入一行字符,分别统计出其中英文字母、空格、数字、和其他字符的个数。
//程序分析:利用while语句,条件为输入的字符不为'\n'.
Scanner sc = new Scanner(System.in);
System.out.println("输入一行字符:要空格");
String str = sc.nextLine(); // 接收一行字符串
int[] arr = f(str);
System.out.println("字母数:" + arr[0] + "\n空格数:" + arr[1] + "\n数字数:" + arr[2] + "\n其他字符:" + arr[3]);
}
public static int[] f(String str){
if (str == null) {
return null;
}
char[] cs = str.toCharArray();
int[] arr = new int[4]; //字母数 空格数 数字数 其他字符
for (int i = 0; i < cs.length; i++){
if ((cs[i] >= 'a' && cs[i] <= 'z') || (cs[i] >= 'A' && cs[i] <= 'Z')){
arr[0]++;
}else if (cs[i] == ' '){
arr[1]++;
}else if (cs[i] >= '0' && cs[i] <= '9'){
arr[2]++;
}else {
arr[3]++;
}
}
return arr;
}
}
a-zA-Z0-9_- ↩︎