Day19知识总结

保证类只能创建出一个对象——单例模式

单例模式创建对象

类构造器私有(private) 不让外部类调用此类构造器函数
类内部 new类,创建对象 自己创建一个对象
提供公开静态方法 通过类名调用静态方法
把自己创建的对象 通过这个静态方法返回

饿汉式

提供私有构造函数[自行定义];
自己创建一个私有对象 [ 私有静态-- 存放置方法区 类加载时就被创建]
提供静态方法,通过类名调用这个静态方法来获取类实例化的对象
把创建的对象,通过这个静态方法返回

//单例模式 饿汉式
public class Demo1Singleton1 {
    private static Demo1Singleton1 s1=new Demo1Singleton1();
    // 在类加载是,对象就会被创建
    private Demo1Singleton1(){
        //私有化构造方法,静止外部直接创建对象
    }
    public static synchronized Demo1Singleton1 getInstance(){ 
       //创建公开静态方法 便于外部调用
       return s1;
    }
}
class Test1{
    public static void main(String[] args) {
        //单例模式 饿汉式
        Demo1Singleton1 t1=Demo1Singleton1.getInstance();
        Demo1Singleton1 t2=Demo1Singleton1.getInstance();
        System.out.println(t1==t2);//true
    }
}

懒汉式

提供私有构造函数;[自行定义]
提供公开静态方法 通过类名调用静态方法
定义一个静态变量
在静态方法中做判断,静态变量为null,则创建对象[new 类];不为null,则返回静态变量[对象]

//单例模式 懒汉式
class Singleton2{
    private static Singleton2 s2;// 定义一个私有静态的变量 默认值为null
    private Singleton2(){
        //构建私有的构造函数
    }
    public static synchronized Singleton2 getInstance(){
        if(s2==null)
            s2=new Singleton2(); //提供公开静态方法 
        //只有在调用静态方法时,才考虑是否创建对象
        return s2;
    }
}
class Test1{
    public static void main(String[] args) {
        //单例默认 懒汉式
        Singleton2 t3=Singleton2.getInstance();
        Singleton2 t4=Singleton2.getInstance();
        System.out.println(t3==t4);//true
    }
}

面试题-单例模式写个冒泡排序

第一, 类满足单例模式
第二, 提供排序方法 [对象调用此方法]

//利用单例写个冒泡排序
//类满足单例
//提供排序方法 对象调用方法
class Singleton3{
    //类满足单例
    private static Singleton3 s3=new Singleton3();
    private Singleton3(){
    }
    public static synchronized Singleton3 getInstance(){
        return s3; //实例化 获取对象
    }
    //提供排序方法
    public int[] maoPao(int[] a){
        for (int i=0;i<a.length-1;i++)
            for(int j=0;j<a.length-1-i;j++){
                if(a[j]>a[j+1]){
                    int t=a[j];
                    a[j]=a[j+1];
                    a[j+1]=a[j];
                }
            }
        return a;
    }
}
class Test1{
    public static void main(String[] args) {
        //利用单例模式写个冒泡排序
        int[] a=null;
        int[] a1={2,3,1,4,6,5};
        //获取单例对象
        Singleton3 t5=Singleton3.getInstance();
        //对象调用方法
        int[] m1=t5.maoPao(a);
        System.out.println(Arrays.toString(m1));
        int[] m2=t5.maoPao(a1);
        System.out.println(Arrays.toString(m2));

    }
}

单例模式:一个类只有一个对象被创建(只实例化一次),这种类就满足单列模式
单例模式

非单例:一个类可创建出多个对象,就是非单例
非单例模式

实例化:创建对象的过程,就是实例化 例如new 类型()
synchronized关键字: 同步;一次只允许一个调用这个方法

String类中的方法使用

字符串.indexOf()

字符串.indexOf(子串)

字符串.indexOf(子串) 找到某个字符串在原字符串的位置
找到就返回这个指定字符串[首字符位置],找不到就返回-1

 public static void main(String[] args) {
        String str="abtomcdtomefto1tom2tom";
//"tom" 是一个子字符串
 //找到字符串tom
//字符串.indexOf(子串) 找到某个字符串在原字符串的位置
//找到就返回这个指定字符串[首字符位置],找不到就返回-1
        int i = str.indexOf("tom"); //2
        int i1 = str.indexOf("tom1"); //-1
    }

字符串.indexOf(子串,n) 从指定位置开始找

 public static void main(String[] args) {
        String str="abtomcdtomefto1tom2tom";
        //"tom" 是一个子字符串
        //从指定位置开始找
        //字符串.indexOf(子串,n) 从指定位置开始找
        int i2=str.indexOf("tom",3);//7
        //统计"tom"的个数
        int a=-1;
        int count=-1;
        do {
            count++;
            a=str.indexOf("tom",a+1);

        }while (a!=-1);
        System.out.println("统计tom的个数:"+count);
    }

字符串.lastIndexOf(),从后往前找

字符串. lastIndexOf(字符串)

从后往前找,找到最后一个出现的字符串的索引位置;
若未找到,返回-1

public static void main(String[] args) {
        String str="abtomcdtomefto1tom2tom";
        //"tom" 是一个子字符串
//lastIndexOf(字符串)
//从后往前找,找到最后一个出现的字符串的索引位置;若未找到,返回-1
        System.out.println(str.lastIndexOf("tom"));//19
    }

字符串. lastIndexOf(字符串,index)

字符串. lastIndexOf(字符串,index),从后往前 指定位置[结尾位置]

public static void main(String[] args) {
        String str="abtomcdtomefto1tom2tom";
        //"tom" 是一个子字符串
        //lastIndexOf(字符串,index),从后往前 指定位置[结尾位置]
        System.out.println(str.lastIndexOf("tom",6));//2
    }

索引超出范围,依旧返回-1

字符串.substring(); 截取子字符串

s.substring(起始位置); 指定起始位置,默认到结尾

String s="tomjackalicerose";
System.out.println(s.substring(0));//tomjackalicerose

s.substring(起始位置,末尾位置);

s.substring(起始位置,末尾位置),指定起始位置到[末尾-1位置];
包含前面,不包含后面

System.out.println(s.substring(0,3));//tom
int i=s.indexOf("jack");
System.out.println(s.substring(i,i+"jack".length()));//jack    
System.out.println(s.substring(s.indexOf("rose"),s.indexOf("rose")+"rose".length()));//rose
三个字母为一组截取为子字符串,保存在字符数组中
方法一
		String str="abcdefghigklmn";
		String[] n=new String[0];
		int m=0;
        int m1=3;
        for(int i1=0;i1<str.length();i1=i1+3){
            String sub;
            if(i1+3>str.length())
                sub=str.substring(i1);
            else{
                sub=str.substring(i1,i1+3);
            };
            n= Arrays.copyOf(n,n.length+1);
            n[n.length-1]=sub;
        }
        System.out.println(Arrays.toString(n));
方法二
String str="abcdefghigklmn";
		String[] n=new String[0];
while (true){
            if(str.length()>3){
                n= Arrays.copyOf(n,n.length+1);
                n[n.length-1]=str.substring(0,3);;
                str=str.substring(3);
            }
            else {
                n= Arrays.copyOf(n,n.length+1);
                n[n.length-1]=str.substring(0);;
                break;
            }
        }
        System.out.println(Arrays.toString(n));

字节数组 & 字符编码

utf-8, 一个中文字符三个字节
gbk , 一个中文两个字节

public static void main(String[] args) throws Exception{
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);
}

正则表达式

正则表达式的介绍

可以出现的字符

[] 任意一个字符
[abc] a、b、c中任意一个

[^] 除此以外的任意一个
[^abc] 除a、b、c以外的任意一个

[a-z && [^bc] ] 在a-z中除b、c的任意一个

可以出现的字符简写

. 任意一个字符

\d 任意一个数字字符[0-9]
\D 任意一个非数字字符 [^0-9 ]

\s 空白字符
\S非空白字符

\w 任意一个单词字符[a-zA-z0-9]
\W 任意一个非单词字符

字符串出现的次数限定

X? 表示0个或1个X
X* 表示0个或任意多个X
X+ 表示1个或任意多个X
X{n} 表示n个X
X{n,} 表示n个到任意多个[大于等于n]
X{n,m} 表示n个到m个X[大于等于n个且小于m个X]

其他规定
其他规定

String中正则表达式的使用

regex : 正则

能出现哪些字符
出现的次数
特殊规定:限定开始,限定结尾
全局查询,忽略大小写

split()方法

split()方法,把字符串按照指定的分隔符,分割为字符串数组

 		String str="aa12321bb3434cc1dd343ee33";
        String regex="[0-9]{1,}";
        String regex1="[^0-9]{1,}";
        String[] split = str.split(regex);
        String[] split1 = str.split(regex1);
        System.out.println(Arrays.toString(split));
        //[aa, bb, cc, dd, ee]
        System.out.println(Arrays.toString(split1));
        //[, 12321, 3434, 1, 343, 33]

        //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]);
        //2023-8-3

“0123456789”,变成0-1-2-3-4-5-6-7-8-9

String old="0123456789";
        regex="";//数字直接有间隔 空字符串
        String[] split2 = old.split(regex);
        String s="";
        for(int i=0;i<split2.length;i++){
            s+="-"+split2[i];
        }
        s=s.substring(1);//去掉首字符
        System.out.println(s);//0-1-2-3-4-5-6-7-8-9

replaceAll()方法

replaceAll()方法,把正则匹配的内容,替换为指定的字符串

“abtomcdtomefto1tom2tom” tom替换为TOM

	    String s2="abtomcdtomefto1tom2tom";
        regex="tom";
        //replaceAll(regex, 替换为str)
        String tom = s2.replaceAll(regex, "TOM");
		old="你妈最近身体好吗,你妹妹最近考上了那个大学.我最喜欢的明星范冰冰,我妈妈也是,因为演技好.";
//        regex="妈{1,}|妹{1,}|冰{1,}";
        regex="[妈妹冰]{1,}";
        String newStr=old.replaceAll(regex,"***");
        System.out.println(newStr);
//你***最近身体好吗,你***最近考上了那个大学.我最喜欢的明星范***,我***也是,因为演技好.

StringBuffer & StringBuilder

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”)........

线程安全

StringBuilder

StringBuilder封装可变的字符串, StringBuilder对象创建后,可以通过调用方法,修改字符串的内容。

StringBuilder构造器函数

public StringBuilder();
 public StringBuilder(String str);

StringBuilder提供的很多方法,返回值是StringBuilder (return this ) , 所以支持链式操作:

StringBuilder sb = new StringBuilder(“a”);
 sb.append(“b”).append(“b”)........

线程不安全

方法使用

append–末尾追加
insert–插入,指定位置之前
delete–删除
replace–替换
reverse–反转

 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());//今天是星期四天气很好
        //替换replace()
        int i=sb.indexOf("星期四");//索引
        sb.replace(i,i+"星期四".length(),"XQS");//今天是XQS天气很好
        System.out.println(sb);
        //删除 delete()
        i=sb.indexOf("是XQS");
        sb.delete(i,i+"是XQS".length());//今天天气很好
        System.out.println(sb);
        //反转 reverse()
        sb.reverse();
        System.out.println(sb);//好很气天天今
        }

判断 "上海自来水来自海上"是否回文

		String str="上海自来水来自海上";
        //判断 "上海自来水来自海上"是否回文
        StringBuilder sb1=new StringBuilder();
        sb1.append(str);
        sb1.reverse();
        if(str.equals(sb1.toString()))//两个字符串比较
            System.out.println("是回文");
        else
            System.out.println("不是回文");

String、StringBuilder和StringBuffer的区别

执行速度来看:String<StringBuffer<StringBuilder

String 类

不可变性: String 对象一 旦被创建,其值就不可更改

每次对string 进行修改(如拼接、裁剪等操作)都会产生一个新的String 对象,原来的对象不变这会导致频繁的对象创建,可能会对性能产生影响

线程安全

由于string 对象不可变,它是线程安全的,可以在多线程环境下共享而无需担心数据致性问题

StringBuffer 类

可变性: StringBuffer 是可变的

可以对其进行增删改查操作而不会创建新的对象,这使得在频繁操作字符串时,更加高效,尤其是涉及大量拼接操作时

.线程安全:

StringBuffer 是线程安全的,所有的方法都经过同步处理,因此可以在多线程环境下使用,但是同 步可能会带来些性能开销

StringBuilder

可变性: StringBuilder 也是可变的,类似于StringBuffer

可以对其进行增删改查操作,但与StringBuffer不同,StringBuilder 并没有进行同步处理,因此在单线程环境下执行操作会更快

线程不安全

由于没有同步处理,StringBuilder 不适合在多线程环境下共享,因为可能导致数据不一致的问题

今日学习题:

给定一个字符串编码规则,如输入字符串"Y3E12S!3",字母后面的数字表示该字符重复几次。
如果字符后没有数字则表示一个字符,最终输出转码后的字符串’ YYYEEEEEEEEEEEES !!!’
试写出转码的函数

将两个字母之间的数字取出

方法一:计数[双层循环]

public static String one(String str){
        String newStr=""; //存放每一次数字
        String newStr1=""; //最终字符串
        int pre=0; //记录每一次数字前的字母位置
        int i=0;//循环的次数
        int count=0;//控制里层循环遇见两次不是数字就终止
        boolean b=true;
        while (b){//死循环
            do {//找出数字
                if(i<=str.length()-1){
                    if(!(str.charAt(i)>='0' && str.charAt(i)<='9')){ 
                        count++;
                        if (count==1) //记录数字前字符的位置
                            pre=i;
                    }
                    else{
                        newStr+=str.charAt(i);//一直是数字就加在一次
                    }
                    i++;//下标累加,直到遇见第二个字符结束
                }
                else{
                    b=false; //小标已经超出长度,则字符已遍历完,结束循环
                    break;
                }
            }while (count<2);
            if(newStr.equals("")){
                newStr1+=str.charAt(pre); //如果数字为""则两个字母连着,没有数字
            }
            else{
                newStr1+=String.valueOf(str.charAt(pre)).repeat(Integer.parseInt(newStr)); 
                //String.valueOf(str.charAt(pre)) 先把字符通过记录下标找出来,再转换为字符串类型
                //Integer.parseInt(newStr) 将字符串转换为Integer类型的数字
                //String1.repeat(Integer.parseInt(newStr));将该字符串重复newStr次数
            }
            count=0; //找到一次清零,继续下一次寻找
            newStr="";//找到一次清零,继续下一次寻找
            i--; //内层循环退出时,i多加了,所以需要i--;
            if (!b)//b为false则遍历结束
                break;
        }
        System.out.println(newStr1);
        return newStr1;
    }

方法二:正则

  public static String two(String str){
        String regex="[0-9]{1,}";
        String regex1="[^0-9]{1,}";
        String[] split = str.split(regex); 
        //取出字符串中所以的数字,有序保存为数组 //[, 8, 12, 15, 4, 4]
        String[] split1 = str.split(regex1);
        //取出字符串中所有的非字符串的数,有序保持为数组 //[YE, S , H, T, T!!]
        
        //由于数字数组首位不要,且需要对最后面做判断
        String newStr="";
        for (int i=0;i<split.length;i++){
            if(i+1>split1.length-1){
                newStr+=split[split.length-1];
                break;
            }
            else
                newStr+=split[i].substring(0,split[i].length()-1)+split[i].substring(split[i].length()-1).repeat(Integer.parseInt(split1[i+1]));
        }
        System.out.println(newStr);
        return newStr;
    }

结果展示

今日学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值