Java.lang中的String类和StringBuilder类介绍和常用方法
目录
Java.lang中的String类和StringBuilder类介绍和常用方法
String类介绍
String类的底层成员介绍
基本介绍
回顾String传址调用问题
String类对象的创建方式
String面试题
创建对象or不创建对象
创建了几个对象and共有几个对象
String常用方法
判断字符串是否相等方法
获取字符串内容方法
字符串转换
根据指定字符分割字符串
其他常用方法
StringBuilder类介绍
StringBuilder原理
StringBuilder的使用
StringBuilder对象创建方式
StringBuilder常用方法
StringBuilder与StringBuffer的区别
Java.lang中的String类和StringBuilder类介绍和常用方法
String类介绍
在Java中,String属于一种引用类型,表示字符串类型。实际上,在Java中,所有字符串字面量都是作为String类的对象实例化的,即使用双引号""包裹的都是String类的对象。
所以使用String s = "abc"表示的是创建了一个String类的对象内容为"abc",而s就是对象名,示意图如下:

根据官方文档对String类的描述,字符串都是常量,其值在创建后不可以被修改,所以在进行字符串拼接等对原始字符串内容进行的操作都是根据结果重新创建了一个新的字符串,例如下面的代码:
String s = "hello";
s += "world"; 当对象s指向了"hello"时,此时堆中存在一个空间,其内容为"hello",而接下来想在原来的字符串中拼接"world"是做不到的,所以将拼接后的结果存入一个新空间返回给s,示意图如下:

因为String类的对象是不可变的,所以当出现内容相同的String对象,则不会二次创建String对象,而是共享已经创建的String对象,例如下面的代码:
public class Test {public static void main(String[] args) {String str1 = "abc";String str2 = "abc";System.out.println(str1 == str2);}
}输出结果:
true String类的底层成员介绍
基本介绍
String类之所以底层的数据不可以修改,是因为底层使用了final修饰了字符串数组,在JDK8时,String底层成员是private final char value[];,而JDK9开始,String底层的成员变为private final byte[] value;。修改存储类型的目的还是为了节省空间
public class Call {public static void main(String[] args) {String arr1 = "字符串";change(arr1);// 方法内的修改不影响main函数arr1System.out.print(arr1);}public static void change(String arr1) {arr1 = "修改字符串";System.out.print(arr1);System.out.println();}
} 回顾String传址调用问题
根据上面的原理,再回顾前面在「传值调用和传址调用」中遇到的String对象通过形参传递
首先,对于Java中的引用数据类型来说,都是传址调用,这里的传址调用表示在方法中可以修改对应形参的内容,例如形参是数组类型时,可以在方法中修改数组中的内容,此时会影响实参
对于String类型,因为其也属于引用数据类型,所以传递给形参,在方法中理论上也可以改变其内容,但是实际上因为String类的属性被final修饰,导致无法在方法中修改其对应的内容,进而不会影响到实参字符串中的内容
而对于直接将对象引用传递给形参本质是实参对象引用的副本,不论是基本数据类型还是引用数据类型,将实参对象引用直接传递形参后,在方法中改变形参对应的对象引用指向都不会影响到方法外的形参对应的实参对应的对象引用指向
例如上面代码中,首先因为字符串不可变,所以"修改字符串"实际上是一块新的String类对象,而arr1 = "修改字符串";只是改变了arr1在方法change中的指向,但是因为arr1是直接传递给形参,所以方法中改变arr1的指向不会影响main函数中的arr1的指向
String类对象的创建方式
在官方文档中,提供了String类的许多构造方式,下面主要介绍常用的几种:
- 使用无参构造创建
String类对象:String() - 使用字符串创建
String对象:String(String original) - 使用
char数组创建String对象:String(char[] value) - 使用平台的默认字符集解码指定的
byte数组,构造一个创建String对象:String(byte[] bytes)
对于第4种创建方式来说,平台表示当前Java代码所在的操作系统,默认字符集表示当前操作系统所使用的字符编码格式,Windows下默认是GBK,解码表示根据byte数组中的数值以及Java所在环境的编码格式进行与字符表对应的字符显示
需要注意,如果是在控制台使用javac编译Java代码,则使用的编码根据操作系统决定,Windows下是GBK,如果使用IDEA,则此时默认情况下是UTF-8,因为IDEA启动编译时会自动加载一个启动参数(-Dfile.encoding=UTF-8),这个启动参数就是指定编码格式为UTF-8,解码时就需要使用UTF-8
如果想修改解码方式,可以在IDEA中进行下面的方式改变编码格式:
File->Settings->展开Editor->选择File Encodings->根据自己需要改变全局编码(Global Encoding)和项目编码(Project Encoding)
下面是上面四种构造方式的使用实例(第4种方式以GBK为例):
需要注意,在GBK编码中,一个中文字符占用2个字节,所以在byte数组中一个中文字符需要使用两个元素,而对于UTF-8编码,一个中文字符占用3个字节,所以在byte数组中一个中文字符需要使用三个元素
public class Test {public static void main(String[] args) {// 1. 使用无参构造创建String类对象:String()String str1 = new String();System.out.println(str1);// 2. 使用字符串创建String对象:String(String original)String str2 = new String("hello");System.out.println(str2);// 3. 使用char数组创建String对象:String(char[] value)char[] chars = {'a', 'b', 'c'};String str3 = new String(chars);System.out.println(str3);// 4. 使用平台的默认字符集解码指定的 byte 数组,构造一个创建String对象:String(byte[] bytes)// ASCII 码byte[] bytes = {97, 98, 99};String str4 = new String(bytes);System.out.println(str4);// GBK 编码byte[] bytes1 = {-60, -29, -70, -61};String str5 = new String(bytes1);System.out.println(str5);}
}输出结果:hello
abc
abc
你好 在实际使用String时,最常用的还是简写形式:
String 对象名 = "字符串" 两种特殊的构造String类对象的方式:
- 取出
char数组中的部分字符构造String类对象:String(char[] value, int offset, int count) - 取出byte数组中的部分字符构造String类对象:
String(byte[] bytes, int offset, int length)
在上面的两种方式中,第一个参数代表对应数据类型的字符数组,第二个参数代表第一个包括的字符(即转换起点字符),第三个参数代表字符个数(从第二个参数代表的字符开始算起)
下面是实例代码:
public class Test {public static void main(String[] args) {// 1. 取出char数组中的部分字符构造String类对象:String(char[] value, int offset, int count)char[] chars1 = {'a', 'b', 'c', 'd', 'e'};String str6 = new String(chars1, 1, 3);System.out.println(str6);// 2. 取出byte数组中的部分字符构造String类对象:String(byte[] bytes, int offset, int length)byte[] bytes1 = {-60, -29, -70, -61};String str7 = new String(bytes1, 0, 2);System.out.println(str7);}
}输出结果:
bcd
你 String面试题
创建对象or不创建对象
思考下面代码的结果:
public class Demo04String {public static void main(String[] args) {String s1 = "abc";String s2 = "abc";String s3 = new String("abc");System.out.println(s1==s2); //trueSystem.out.println(s1==s3); //falseSystem.out.println(s2==s3); //false}
} 在上面的代码中,因为相同内容的字符串会共享,所以s1与s2实际上指向的是同一块空间,但是对于s3来说,因为使用了new关键字,所以在堆内存创建了一块新空间,但是这块空间的内容因为与s1和s2对应的字符串的内容相同,所以依旧是共享一块空间,但是s3指向的new开辟的新空间的地址,所以s3与s1和s2都不相同,示意图如下:

思考下面的代码结果:
public class Test02 {public static void main(String[] args) {String s1 = "hello";String s2 = "world";String s3 = "helloworld";String s4 = "hello"+"world";String s5 = s1+"world";String s6 = s1+s2;System.out.println(s3==s4); //trueSystem.out.println(s3==s5); //falseSystem.out.println(s3==s6); //false}
} 对于上面的代码来说,如果.class文件反编译成.java文件,就可以明白结果出现的原因,下面是反编译的结果:

可以看到,对于使用+两侧全是字符串常量直接拼接的,直接将拼接结果与其他字符串比对是否存在可共享的字符串,如果存在则直接使用;对于存在变量使用+进行拼接,则会调用StringBuilder()中的方法进行拼接,因为使用了new关键字,所以对象引用指向的空间地址并不是内容相同的字符串常量的地址
创建了几个对象and共有几个对象
思考下面的代码,回答:
- 对于第一行代码来说,创建了几个对象,共有几个对象
- 对于第二行代码来说,创建了几个对象,共有几个对象
String s1 = "abc"; // 1String s2 = new String("hello"); // 2 对于第一行代码来说,因为字符串在Java中属于String类的实例,即"abc"属于String类的对象,使s1指向了该对象,因此一共创建了1个对象,共有1个对象
对于第二行代码来说,首先"hello"会作为对象先创建,但是题目并没有说明在String s2 = new String("hello");之前是否已经创建了"hello"字符串对象,如果未创建,则包括new创建的对象在内一共创建了2个对象,共有2个对象;如果已经创建,根据字符串共享性,则包括new创建的对象在内一共创建了1个对象,共有2个对象
String常用方法
需要注意,String类的方法不仅是对象引用变量可以调用,字符串常量也可以调用,因为字符串常量也是String类的对象
判断字符串是否相等方法
boolean equals(String s)方法:因为String类重写了父类Object中的equals()方法,所以此处比较的字符串中的内容是否相等boolean equalsIgnoreCase(String s)方法:与equals()方法效果基本一致,只是忽略字母大小写
使用实例如下:
public class Test03 {public static void main(String[] args) {String s1 = "abc";String s2 = new String("abc");String s3 = "Abc";System.out.println(s1==s2);//比较地址值//boolean equals(String s)System.out.println(s1.equals(s2));//boolean equalsIgnoreCase(String s)System.out.println(s1.equalsIgnoreCase(s3));}
} 需要注意,上面的两个方法因为是对象调用,所以可能存在调用对象为空(null),为了避免出现空指针异常,也可以使用工具类java.util.Objects中的equals()方法进行比较,使用方式如下:
private static void method(String s1, String s2) {// 使用工具类Objects中的equals方法if (Objects.equals(s1, s2)) {System.out.println("相同字符串");} else{System.out.println("不相同字符串");}
} 下面是Objects工具类中的equals()方法源码:
public static boolean equals(Object a, Object b) {return (a == b) || (a != null && a.equals(b));
} 获取字符串内容方法
- 获取字符串长度:
int length()
这里的获取长度是方法,不同于数组中的 length是数组的属性 - (拼接)拼接调用对象字符串和参数字符串:
String concat(String s),返回一个新字符串的地址 - (字符下标)获取调用对象字符串中参数对应下标的字符:
char charAt(int index) - (查找字符)获取参数字符第一次在调用对象字符串中出现的位置:
int indexOf(String s) - (截取字符串)在调用对象字符串获取从参数位置开始(包括参数位置)之后的字符串,一直到最后一个字符:
String subString(int beginIndex),返回一个新字符串 - (截取字符串)在调用对象字符串获取从参数位置开始(包括参数位置)之后的字符串,一直到第二个参数的位置对应的字符前一个字符(含第一个参数对应的字符,不含第二个参数对应的字符):
String subString(int beginIndex,int endIndex),返回一个新字符串
基本使用实例如下:
public class Test03 {public static void main(String[] args) {String s1 = "abcdefg";//int length()System.out.println(s1.length());//String concat(String s)System.out.println(s1.concat("haha"));//char charAt(int index)System.out.println(s1.charAt(0));//int indexOf(String s)System.out.println(s1.indexOf("a"));//String subString(int beginIndex)System.out.println(s1.substring(3));//String subString(int beginIndex,int endIndex)System.out.println(s1.substring(1, 6));}
}输出结果:
7
abcdefghaha
a
0
defg
bcdef 使用上面的方法遍历字符串:
public class Test03 {public static void main(String[] args) {String s = "abcdefg";for (int i = 0; i < s.length(); i++) {System.out.println(s.charAt(i));}}
} 字符串转换
- 将字符串转换成
char数组:char[] toCharArray() - 将字符串转换成
byte数组:byte[] getBytes() - 替换字符串中的字符:
String replace(CharSequence c1,CharSequence c2) - 按照指定的编码将字符串转成
byte数组:byte[] getBytes(String charsetName),注意本方法会抛出异常
第三种方法中的CharSequence是String类实现的接口,所以根据多态(向上转型),可以直接传递String类对象
基本使用如下:
public class Test04 {public static void main(String[] args) throws UnsupportedEncodingException {String s = "abcdefg";//1.char[] toCharArray()char[] chars = s.toCharArray();for (int i = 0; i < chars.length; i++) {System.out.print(chars[i] + " ");}System.out.println();//2.byte[] getBytes()byte[] bytes = s.getBytes();for (int i = 0; i < bytes.length; i++) {System.out.print(bytes[i] + " ");}System.out.println();//3.String replace(CharSequence c1,CharSequence c2)System.out.println(s.replace("a","z"));//4.byte[] getBytes(String charsetName)byte[] bytes1 = "你好".getBytes("GBK");for (int i = 0; i < bytes1.length; i++) {System.out.print(bytes1[i] + " ");}}
}输出结果:
a b c d e f g
97 98 99 100 101 102 103
zbcdefg
-60 -29 -70 -61 根据指定字符分割字符串
使用方法:String[] split(String regex)
注意,方法的参数是正则表达式,如果想使用.进行分割,需要对.进行转义:\\.
使用实例如下:
public class Test05 {public static void main(String[] args) {String s = "abc,txt";String[] split = s.split(",");for (int i = 0; i < split.length; i++) {System.out.println(split[i]);}String s2 = "haha.hehe";String[] split1 = s2.split("\\.");for (int i = 0; i < split1.length; i++) {System.out.println(split1[i]);}}
}输出结果:
abc
txt
haha
hehe 其他常用方法
- 调用对象字符串是否包含参数中的字符串:
boolean contains(String s) - 调用对象字符串是否以参数字符串结尾:
boolean endsWith(String s) - 调用对象字符串是否以参数字符串开头:
boolean startsWith(String s) - 调用字符串中的大写字母转小写(本身为小写的不改变):
String toLowerCase() - 调用字符串中的小写字母转大写(本身为大写的不改变):
String toUpperCase() - 去掉字符串首尾空格(不会去除字符串内容中的空格):
String trim()
基本使用如下:
public class Test06 {public static void main(String[] args) {String s = "abcdefg";//1.boolean contains(String s)System.out.println(s.contains("a"));//2.boolean endsWith(String s)System.out.println(s.endsWith("g"));//3.boolean startsWith(String s)System.out.println(s.startsWith("a"));//4.String toLowerCase()-> 将字母转成小写System.out.println("ADbcda".toLowerCase());//5.String toUpperCase() -> 将字母转成大写System.out.println("dafadRWERW".toUpperCase());//6.String trim()System.out.println(" hadfhad hdsfha sfhdsh ".trim());// 拓展:使用替换字符串内容中的空格System.out.println("hadfhad hdsfha sfhdsh".replace(" ",""));}
}输出结果:
true
true
true
adbcda
DAFADRWERW
hadfhad hdsfha sfhdsh
hadfhadhdsfhasfhds StringBuilder类介绍
与String不同的是,StringBuilder是一个可变的字符序列,并且该类提供了一个与StringBuffer兼容的一套API,但是不保证同步,导致线程不安全,但是效率高,一般用于字符串拼接
之所以使用StringBuilder类进行拼接而不是String拼接是因为StringBuilder类的字符串可以改变,所以拼接可以在原字符串上拼接,但是String必须创建一个新对象,如果拼接次数太多,String就会影响整体效率
StringBuilder原理
StringBuilder类底层自带一个缓冲区(没有被final修饰的byte数组)拼接字符串之后都会在此缓冲区中保存,在拼接的过程中,不会随意产生新对象,节省内存,其特点是:
- 底层自带缓冲区,此缓冲区是没有被
final修饰的byte数组,默认长度为16 - 如果字符串超出了已有的数组长度,数组会自动扩容,默认扩容大小是原来数组长度的2倍+2,但是如果扩容后的长度依旧不够,则会根据字符串的长度确定数组长度
StringBuilder的使用
StringBuilder对象创建方式
- 无参构造方法:
StringBuilder() - 使用
String构造StringBuilder对象:StringBuilder(String str)
使用实例如下:
public class Test06 {public static void main(String[] args) {StringBuilder sb = new StringBuilder();System.out.println(sb);StringBuilder sb1 = new StringBuilder("abc");System.out.println(sb1);}
} StringBuilder常用方法
- 字符串追加:
StringBuilder append(任意类型数据),与String拼接不同,在原字符串基础上拼接,不会创建新对象 - 字符串翻转:
StringBuilder reverse(),返回原字符串翻转后的结果,不会创建新对象 StringBuilder转String:String toString(),转换是为了便于后面使用String的方法
基本使用实例:
public class Test {public static void main(String[] args) {StringBuilder sb = new StringBuilder();StringBuilder sb1 = sb.append("abc");System.out.println(sb1);System.out.println(sb);System.out.println(sb==sb1);//链式调用sb.append("def").append("g").append("f");System.out.println(sb);sb.reverse();System.out.println(sb);String s = sb.toString();System.out.println(s);}
}输出结果:
abc
abc
true
abcdefgf
fgfedcba
fgfedcba 方法实用:
判断一个字符串是否是「回文字符串」:
public class Test01 {public static void main(String[] args) {String str = "abcba";StringBuilder sb = new StringBuilder(str);// 使用StringBuilder中的reverse方法反转字符串,反转完后转换为String使用其equals方法判断内容是否相同,如果反转与原字符串相等,则是回文串boolean result = sb.reverse().toString().equals(str);System.out.println(result);}
} StringBuilder与StringBuffer的区别
相同点:
用法一样,作用一样
不同点:
StringBuilder:拼接效率比StringBuffer和String高,但是线程不安全StringBuffer:效率比较底,但是线程安全
- 拼接效率:
StringBuilder>StringBuffer>String
相关文章:
Java.lang中的String类和StringBuilder类介绍和常用方法
目录 Java.lang中的String类和StringBuilder类介绍和常用方法 String类介绍 String类的底层成员介绍 基本介绍 回顾String传址调用问题 String类对象的创建方式 String面试题 创建对象or不创建对象 创建了几个对象and共有几个对象 String常用方法 判断字符串是否相等方法 获取字…...
notepad++软件介绍(含安装包)
Notepad 是一款开源的文本编辑器,主要用于编程和代码编辑。它是一个功能强大的替代品,常常被用来替代 Windows 系统自带的记事本。 Notepad win系统免费下载地址 以下是 Notepad 的一些主要特点和功能: 多语言支持:Notepad 支持多…...
chapter13-常用类——(章节小结)——day17
498-常用类阶段梳理...
RTX AI PC 和工作站上部署多样化 AI 应用支持 Multi-LoRA
今天的大型语言模型(LLMs)在许多用例中都取得了前所未有的成果。然而,由于基础模型的通用性,应用程序开发者通常需要定制和调整这些模型,以便专门针对其用例开展工作。 完全微调需要大量数据和计算基础设施࿰…...
C++ STL-deque容器入门详解
1.1 deque容器基本概念 功能: 双端数组,可以对头端进行插入删除操作 deque与vector区别: vector对于头部的插入删除效率低,数据量越大,效率越低deque相对而言,对头部的插入删除速度回比vector快vector访…...
数据结构之折半查找
折半查找(Binary Search),也称为二分查找,是一种在有序数组中查找特定元素的搜索算法。其工作原理是,通过不断将待查找的区间分成两半,并判断待查找的元素可能存在于哪一半,然后继续在存在可能性…...
linux高级学习12
24.9.9学习目录 一.条件变量 一.条件变量 通常条件变量和互斥锁同时使用; 条件变量是用来阻塞线程,其本身并不是锁,直到达到特定的要求; (1)条件变量初始化 #include <pthread.h> int pthread_con…...
leetcode:3174 清除数字 使用栈,时间复杂度O(n)
3174 清除数字 题目链接 题目描述 给你一个字符串 s 。 你的任务是重复以下操作删除 所有 数字字符: 删除 第一个数字字符 以及它左边 最近 的 非数字 字符。 请你返回删除所有数字字符以后剩下的字符串。 示例 1: 输入:s "abc…...
神经网络卷积操作
文章目录 一、nn.Conv2d二、卷积操作原理三、代码实现卷积操作 一、nn.Conv2d nn.Conv2d 是 PyTorch 中的一个类,它代表了一个二维卷积层,通常用于处理图像数据。在深度学习和计算机视觉中,卷积层是构建卷积神经网络(CNN…...
专题二_滑动窗口_算法专题详细总结
目录 滑动窗口,引入: 滑动窗口,本质:就是同向双指针; 1.⻓度最⼩的⼦数组(medium) 1.解析:给我们一个数组nums,要我们找出最小子数组的和target,首先想到的…...
【机器学习-三-无监督学习】
无监督学习 什么是无监督学习分类聚类降维 有监督和无监督学习的区别 上一节介绍了监督学习,下面来介绍无监督学习,这也是最广泛应用的算法。 什么是无监督学习 上一节中,我们知道了监督学习是通过 对算法,**输入一对数据&#x…...
JAVA基础:Lambda表达式(上)
前言 Lambda表达式是jdk1.8的一个新特性,他属于一种语法堂主要作用是对匿名内部类语法简化 lambda基本应用 lambda表达式想要优化匿名内部类是有前提条件,首先必须是一个接口,而且要求接口中只能有1个抽象方法,称之为函数式接口…...
Vue使用fetch获取本地数据
(1)使用get test.json文件 { "list":[111,222,333] } <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initi…...
《酒饮真经》秘籍4,让你的酒场技巧更上一层楼!
在酒桌这一独特的舞台上,每个人都扮演着不同的角色,或攻或守,尽显智慧与风度。对于不擅长喝酒的人来说,如何在推杯换盏间既保护自己又不失礼节,是值得我们仔细研究的。下面是酱酒亮哥为您整理的一系列实用的酒桌攻防秘…...
回车符与快捷键记录
一.在Windows和Linux操作系统中,回车符(或称为换行符)的处理方式区别 1.Windows下的回车符 在Windows系统中,回车符通常是由两个字符组成的序列:回车符(Carriage Return,简称CR,AS…...
计算机网络-VRRP工作原理
一、VRRP工作原理 前面我们大概了解了VRRP的一些基础概念,现在开始学习VRRP的技术原理。VRRP的选举及工作步骤: 确定网关地址 选举主备 主设备发送VRRP报文通知Backup设备 主设备响应终端ARP并维持在Master状态 终端正常发送报文到网关进行转发 因为我们…...
6.5椒盐噪声
在OpenCV中联合C给一张图片加上椒盐噪声(Salt and Pepper Noise)可以通过随机选择像素点并将其置为黑色(0)或白色(255)来实现。椒盐噪声是一种随机噪声,通常表现为图像中的孤立黑点(…...
CSS样式的引用方式以及选择器使用
1. CSS 引用方式 CSS 可以通过三种方式引用到 HTML 文件中: 行内样式(Inline Styles):直接在 HTML 元素中定义样式。内部样式表(Internal CSS):在 HTML 文档的 <head> 部分使用 <sty…...
Python Flask_APScheduler定时任务的正确(最佳)使用
描述 APScheduler基于Quartz的一个Python定时任务框架,实现了Quartz的所有功能。最近使用Flask框架使用Flask_APScheduler来做定时任务,在使用过程当中也遇到很多问题,例如在定时任务调用的方法中需要用到flask的app.app_context()时&#…...
Linux命名管道
通信的前提是让不同的进程看到同一份资源,因为路径是具有唯一性的,所以我们可以使用路径文件名来唯一的让不同进程看到同一份资源,实现没有血缘关系的两个进程进行管道通信 1.指令级 mkfifio(FILENAME,0666) …...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
