当前位置: 首页 > news >正文

【深入了解Java String类】

目录

String类

常用方法

字符串的不可变性

String的内存分析 

StringBuilder类

解释可变和不可变字符串

常用方法

面试题:String,StringBuilder,StringBuffer之间的区别和联系

String类的OJ练习


String类

【1】直接使用,无需导包:


【2】形象说一下字符串:

【3】


String str = “abc”;
"abc"就是String类下的一个具体的对象

【4】字符串是不可变的:

【5】这个String类不可以被继承,不能有子类:


【6】String底层是一个char类型的数组


验证:

注意:没有用'\0'来标识结尾

String类中的字符实际保存在内部维护的value字符数组
value被final修饰,表明value自身的值不能改变,即不能引用其它字符数组
但是其引用空间中的内容可以修改

常用方法

【1】构造器:底层就是给对象底层的value数组进行赋值操作。

//通过构造器创建对象:
String s1 = new String();
String s2 = new String("abc");
String s3 = new String(new char[]{'a', 'b', 'c'});

【2】常用方法:  

String s4= "abc";
System.out.println("字符串的长度为:"+s4.length());
String s5 = new String("abc");
System.out.println("字符串是否为空:"+s5.isEmpty());
System.out.println("获取字符串的下表对应的字符为:"+s5.charAt(1));

 【3】equals:比较两个值的内容是否相同

String s6 = new String("abc");
String s7 = new String("abc");
System.out.println(s6.equals(s7));
/*String s6 = new String("abc");
String s7 = new String("abc");
System.out.println(s6.equalsIgnoreCase(s7));//忽略大小写*/

equals底层:

【4】String类实现了Comparable接口,里面有一个抽象方法叫compareTo,所以String中一定要对这个方法进行重写
比较两个值的内容的大小,相等返回0,大于返回一个整数,小于返回一个负数

String s8 = new String("abc");
String s9 = new String("accdef");
System.out.println(s8.compareTo(s9));
/*String s8 = new String("abc");
String s9 = new String("Abc");
System.out.println(s8.compareToIgnoreCase(s9));//忽略大小写
*/

compareTo底层:

【5】其它常用方法: 

        //字符串的截取:String s10 = "abcdefghijk";System.out.println(s10.substring(3));System.out.println(s10.substring(3,6));//[3,6)//字符串的拼接/合并:System.out.println(s10.concat("pppp"));//字符串中的字符的替换:String s11 = "abcdeahija";System.out.println(s11.replace('a','u'));//按照指定的字符串进行分裂为数组的形式:String s12 = "a-b-c-d-e-f";String[] strs = s12.split("-");System.out.println(Arrays.toString(strs));//转大小写的方法:String s13 = "abc";System.out.println(s13.toUpperCase());System.out.println(s13.toUpperCase().toLowerCase());//去除首尾空格:String s14 = "   a  b  c   ";System.out.println(s14.trim());//toString()String s15 = "abc";System.out.println(s15.toString());//转换为String类型:传入任何类型的数据都将转换为String类型System.out.println(String.valueOf(String.valueOf(false)));

【6】String类的练习: 

public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {String str = "  hello  themyth      ";System.out.println(str);String ret = str.trim();//去掉的字符串开头和结尾的空白字符(空格、换行、制表符等)System.out.println(ret);String string  = "themyth@ws";System.out.println(string.contains("ws"));//判断字符串里面是否包含了这个内容。}//这是一个main方法,是程序的入口:public static void main2(String[] args) {//字符串的拆分:String str1 = "hello handsome themyth";String[] strs = str1.split(" ");/*for (String s : strs) {System.out.println(s);}*/for (int i = 0; i < strs.length; i++) {System.out.println(strs[i]);//hello//handsome//themyth}String[] strs2 = str1.split(" ", 2);for (int i = 0; i < strs2.length; i++) {System.out.println(strs2[i]);//hello//handsome themyth}String str2 = "192.168.0.1";String[] strs3 = str2.split("\\.");for (int i = 0; i < strs3.length; i++) {System.out.println(strs3[i]);//192//168//0//1}System.out.println("===");String str3 = "192\\168\\0\\1";String[] strs4 = str3.split("\\\\");//  "\\"表示一个"\"for (int i = 0; i < strs4.length; i++) {System.out.println(strs4[i]);//192//168//0//1}System.out.println("===");String str4 = "192&168=1";String[] strs5 = str4.split("&|=");//for (int i = 0; i < strs5.length; i++) {System.out.println(strs5[i]);//192//168//1}System.out.println("===");//多次拆分:String message = "name=themyth&age=22";String[] ms = message.split("&|=");for (String s : ms) {System.out.println(s);//name//themyth//age//22}System.out.println("===");String message2 = "name=themyth&age=22";String[] ms2 = message2.split("&");for (int i = 0; i < ms2.length; i++) {String[] ms3 = ms2[i].split("=");for (String s : ms3) {System.out.println(s);//name//themyth//age//22}}//字符串的截取:String str = "abcdefgh";String s1 = str.substring(2);//cdefgh 返回从2位置开始所截去的字符System.out.println(s1);String s2 = str.substring(2,6);//cdef 截取下标区间[2,6)的字符System.out.println(s2);}//这是一个main方法,是程序的入口:public static void main1(String[] args) {String str1 = "themyth";char ch = str1.charAt(1);//h 下标对应的字符System.out.println(ch);for (int i = 0; i < str1.length(); i++) {if (i != str1.length() - 1) {System.out.print(str1.charAt(i) + " ");} else {System.out.println(str1.charAt(i));}}//t h e m y t hString str2 = "ababcabcabc";int b = str2.indexOf('b');//1 字符第一次出现位置的下标,默认从下标为0开始查找System.out.println(b);int b1 = str2.indexOf('b', 5);//6 从下标为5的字符开始查找,字符第一次出现位置的下标System.out.println(b1);//在主串中 查找子串int abc = str2.indexOf("abc");System.out.println(abc);//2 返回"abc"首字符a第一次出现的位置int b2 = str2.lastIndexOf('b');//9 从后往前找,字符第一次出现位置的下标System.out.println(b2);int b3 = str2.lastIndexOf('b', 5);//3 从下标为5的字符从后往前开始查找,字符第一次出现位置的下标System.out.println(b3);int b4 = str2.lastIndexOf("abc", 7);//5 从下标为7的字符从后往前找子串,如果找到了第一个能够匹配的字串,返回该子串的第一个字符System.out.println(b4);String str3 = String.valueOf(123);//将...转换为字符串System.out.println(str3);String str4 = "123";int data = Integer.parseInt(str4);System.out.println(data);Double data2 = Double.parseDouble(str4);System.out.println(data2);//123.0String str5 = "TheMyth";String str6 = "themyth";System.out.println(str5.toLowerCase());//themythSystem.out.println(str6.toUpperCase());//THEMYTHString str7 = "abcdef";char[] chars = str7.toCharArray();//字符串--->字符数组for (int i = 0; i < chars.length; i++) {if (i != chars.length - 1) {System.out.print(chars[i] + " ");} else {System.out.println(chars[i]);}}//a b c d e fString str8 = new String(chars);//字符数组->字符串System.out.println(str8);String str9 = String.format("%d-%d-%d", 2021, 6, 16);//格式化打印(用的很少)System.out.println(str9);//参数不同。replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替    //换;replaceAll的参数是regex,即基于规则表达式的替换。//替换方式不同。replace是全部替换,即把源字符串中的某一字符或字符串全部换成指定的字符或            //字符串;replaceAll也是全部替换,但如果所用的参数据不是基于规则表达式的,则只替换第一 //次出现的字符串。String str10 = "abcabcdabcde";String replace = str10.replace('a', 'o');//obcobcdobcdeSystem.out.println(replace);String replace1 = str10.replace("abc", "x");//xxdxdeSystem.out.println(replace1);String replace2 = str10.replaceAll("abc", "ooo");//oooooodooodeSystem.out.println(replace2);String replace3 = str10.replaceFirst("abc", "520");//520abcabcdeSystem.out.println(replace3);//注意:字符串是不可变的对象,替换不修改当前字符串!}
}

字符串的不可变性

所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象
例如:substring,返回的都是一个新的字符串对象

public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {String str1 = "abc";String str2 = new String("abc");System.out.println(str1 == str2);//false}
}

public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {String str1 = "abc";String str2 = "abc";System.out.println(str1 == str2);//true}
}

总结“”双引号里面的值存在字符串常量池中,
如果已经存过一次了,就不会进行第二次存储,
直接返回字符串常量池的对象即可 

【纠正】网上有些人说:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变。这种说法是错误的,不是因为String类自身,或者其内部value被final修饰而不能被修改。
final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的
例如: 

import java.util.Arrays;
public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {final int[] array = new int[]{1, 2, 3, 4};array[0] = 666;//指向的内容可以修改//array = new int[]{1, 2, 3, 4, 5};指向本身不能修改System.out.println(Arrays.toString(array));//[666, 2, 3, 4]}
}

真实的原因是:
在String类中是压根拿不到value[ ]的值,因为根本就没有提供设置和获取value的方法
所以字符串不可变的

为什么 String 要设计成不可变的?(不可变对象的好处是什么?) 
1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了. 
2. 不可变对象是线程安全的. 
3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.

String的内存分析 

【1】字符串拼接:

public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {String s1 = "a"+"b"+"c";String s2 = "ab"+"c";String s3 = "a"+"bc";String s4 = "abc";String s5 = "abc"+"";}
}

上面的字符串,会进行编译器优化,直接合并成为完整的字符串,我们可以反编译验证: 

然后在常量池中,常量池的特点是第一次如果没有这个字符串,就放进去,如果有这个字符串,就直接从常量池中取:

内存:

 【2】new关键字创建对象:

String s6 = new String("abc");

内存:开辟两个空间(1.字符串常量池中的字符串 2.堆中的开辟的空间) 

【3】有变量参与的字符串拼接: 

public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {String a = "abc";String b = a + "def";System.out.println(b);}
}

a变量在编译的时候不知道a是“abc”字符串,所以不会进行编译期优化,不会直接合并为“abcdef” 

反汇编过程:为了更好的帮我分析字节码文件是如何进行解析的:

利用IDEA中的控制台:

字符串修改:

public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {/*String str = "hello";str += "abc";System.out.println(str);for (int i = 0; i < 10; i++) {str += "abc";//不建议在循环中使用+对字符进行拼接,要创建很多临时的对象,效率低}*///在底层的代码:String str = "hello";//对象StringBuilder sb = new StringBuilder();//对象sb.append(str);sb.append("abc");//对象str = sb.toString();//对象//共创建了4个对象,所以上面那种写法很不好,如果还是在循环里面进行字符拼接,那效率更低System.out.println(str);}
}

尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。

public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {long start = System.currentTimeMillis();String s = "";for (int i = 0; i < 10000; ++i) {s += i;}long end = System.currentTimeMillis();System.out.println(end - start);start = System.currentTimeMillis();StringBuffer sbf = new StringBuffer("");for (int i = 0; i < 10000; ++i) {sbf.append(i);}end = System.currentTimeMillis();System.out.println(end - start);start = System.currentTimeMillis();StringBuilder sbd = new StringBuilder("");for (int i = 0; i < 10000; ++i) {sbd.append(i);}end = System.currentTimeMillis();System.out.println(end - start);}
}

可以看到在对String类进行修改时,效率是非常慢的,
因此:尽量避免对String的直接修改,如果要修改建议尽量使用StringBuffer或StringBuilder 

StringBuilder类

【1】字符串的分类:
(1)不可变字符串:String
(2)可变字符串:StringBuilder,StringBuffer

【2】StringBuilder底层:非常重要的两个属性: 

【3】对应内存分析:  

从源码分析:

因为value数组被使用了,所以count的值要发生改变
最后返回当前构建的那个对象,实际上在底层就是返回一个复制之后的数组。 

注意:count是StringBuilder底层那个value数组被使用的长度
上述说的第几步到第几步不是真正程序执行的步骤,是自定义,方便自己理解的步骤。 

 

 从源码分析新传入的7个o在底层怎样运作的:

public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {//创建StringBuilder的对象:StringBuilder sb3 = new StringBuilder();//表面上调用StringBuilder的空构造器,实际底层是对value数组进行初始化,长度为16StringBuilder sb2 = new StringBuilder(3);//表面上调用StringBuilder的有参构造器,传入一个int类型的数,实际底层就是对value数组进行初始化,长度为你传入的数字StringBuilder sb = new StringBuilder("abc");System.out.println(sb.append("def").append("aaaaaaaa").append("bbb").append("ooooooo").toString());//链式调用方式:return this}
}

 

解释可变和不可变字符串

【1】String---》不可变

【2】StringBuilder---》可变
可变,在StringBuilder这个对象的地址不变的情况下,想把“abc”变成“abcdef”是可能的,直接追加即可  

public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {StringBuilder sb = new StringBuilder();System.out.println(sb.append("abc") == sb.append("def"));//true,同一个对象}
}

常用方法

【1】StringBuilder常用方法:

public class TestStringBuilder {//这是一个main方法,是程序的入口:public static void main(String[] args) {StringBuilder sb = new StringBuilder("nihaojavawodeshijie");//增sb.append("这是梦想");System.out.println(sb);//nihaojavawodeshijie这是梦想//删sb.delete(3,6);//删除位置在[3,6)上的字符System.out.println(sb);//nihavawodeshijie这是梦想sb.deleteCharAt(16);//删除位置在16上的字符System.out.println(sb);//nihavawodeshijie是梦想//改-->插入StringBuilder sb1 = new StringBuilder("$23445980947");sb1.insert(3,",");//在下标为3的位置上插入","System.out.println(sb1);//$23,445980947//改-->替换StringBuilder sb2 = new StringBuilder("$2你好吗5980947");sb2.replace(3,5,"我好累");//在下表[3,5)位置上替换字符串System.out.println(sb2);//$2你我好累5980947sb.setCharAt(3,'!');System.out.println(sb);//nih!vawodeshijie是梦想//查StringBuilder sb3 = new StringBuilder("asdfa");for (int i = 0; i < sb3.length(); i++) {System.out.print(sb3.charAt(i)+"\t");//a	s	d	f	a}System.out.println();//截取String str = sb3.substring(2,4);//截取[2,4)返回的是一个新的String,对StringBuilder没有影响System.out.println(str);//df//反转sb3.reverse();System.out.println(sb3);//afdsa}
}

【2】StringBuffer常用方法:   与StringBuilder一致,他们的父类都是AbstractStringBuilder

public class Test03 {//这是一个main方法,是程序的入口:public static void main(String[] args) {StringBuffer sb = new StringBuffer("nihaojavawodeshijie");//增sb.append("这是梦想");System.out.println(sb);//nihaojavawodeshijie这是梦想//删sb.delete(3,6);//删除位置在[3,6)上的字符System.out.println(sb);//nihavawodeshijie这是梦想sb.deleteCharAt(16);//删除位置在16上的字符System.out.println(sb);//nihavawodeshijie是梦想//改-->插入StringBuffer sb1 = new StringBuffer("$23445980947");sb1.insert(3,",");//在下标为3的位置上插入 ,System.out.println(sb1);//$23,445980947//改-->替换StringBuffer sb2 = new StringBuffer("$2你好吗5980947");sb2.replace(3,5,"我好累");//在下表[3,5)位置上插入字符串System.out.println(sb2);//$2你我好累5980947sb.setCharAt(3,'!');System.out.println(sb);//nih!vawodeshijie是梦想//查StringBuffer sb3 = new StringBuffer("asdfa");for (int i = 0; i < sb3.length(); i++) {System.out.print(sb3.charAt(i)+"\t");//a	s	d	f	a}System.out.println();//截取String str = sb3.substring(2,4);//截取[2,4)返回的是一个新的String,对StringBuilder没有影响System.out.println(str);//df//反转sb3.reverse();                                                                                        System.out.println(sb3);//afdsa}
}

String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。
频繁修改字符串的情况考虑使用StringBuilder。

注意:String和StringBuilder类不能直接转换。
如果要想互相转换,可以采用如下原则: 
String变为StringBuilder: 利用StringBuilder的构造方法或append()方法 
StringBuilder变为String: 调用toString()方法。

面试题:String,StringBuilder,StringBuffer之间的区别和联系

(1)String、StringBuffer、StringBuilder区别与联系

1. String类是不可变类,即一旦一个String对象被创建后,包含在这个对象中的字符序列是不可改变的,直至这个对象销毁。

2. StringBuffer类则代表一个字符序列可变的字符串,可以通过append、insert、reverse、setChartAt、setLength等方法改变其内容。一旦生成了最终的字符串,调用toString方法将其转变为String。

3. JDK1.5新增了一个StringBuilder类,与StringBuffer相似,构造方法和方法基本相同。

StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作,即StringBuffer是线程安全的,而StringBuilder是线程不安全的,所以性能略高。

通常情况下,创建一个内容可变的字符串,应该优先考虑使用StringBuilder

StringBuilder:JDK1.5开始  效率高   线程不安全

StringBuffer:JDK1.0开始   效率低    线程安全

StringBuilder没有synchronized
而StringBuffer有synchronized

(2)以下总共创建了多少个String对象【前提不考虑常量池之前是否存在】

String str = new String("ab"); // 会创建多少个对象
String str = new String("a") + new String("b"); // 会创建多少个对象

String类的OJ练习

(1)字符串中的第一个唯一的字符

题目链接:https://leetcode.cn/problems/first-unique-character-in-a-string/

class Solution {public int firstUniqChar(String s) {//int[] count = new int[256];int[] count = new int[26];// 统计每个字符出现的次数for (int i = 0; i < s.length(); ++i) {count[s.charAt(i) - 'a']++;}// 找第一个只出现一次的字符for (int i = 0; i < s.length(); ++i) {if (1 == count[s.charAt(i) - 'a']) {return i;}}return -1;}
}

(2)字符串中最后一个单词的长度

题目链接:https://www.nowcoder.com/practice/8c949ea5f36f422594b306a2300315da?tpId=37&&tqId=21224&rp=5&ru=/activity/oj&qru=/ta/huawei/question-ranking

import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseString s = in.nextLine();// 1. 找到最后一个空格// 2. 获取最后一个单词:从最后一个空格+1位置开始,一直截取到末尾// 3. 打印最后一个单词长度int index = s.lastIndexOf(" ");String ret = s.substring(index+1);System.out.println(ret.length());}}
}

(3)验证回文串

题目链接:https://leetcode.cn/problems/valid-palindrome/ 

class Solution {public boolean isPalindrome(String s) {s = s.toLowerCase();int left = 0;int right = s.length() - 1;while (left < right) {//不是有效字符就++遍历下个字符,有可能有多个空格,所以要用while,还有个前提是全程一直要left < right,因为有可能一直都没有遇到有效字符,left >= rightwhile (left < right && !isValidChar(s.charAt(left))) {left++;}//left是有效字符了while (left < right && !isValidChar(s.charAt(right))) {right--;}//right是有效字符了if (s.charAt(left) != s.charAt(right)) {return false;} else {left++;right--;}}return true;}private boolean isValidChar(char ch) {if (Character.isDigit(ch) || Character.isLetter(ch)) {return true;}return false;/*if (ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z') {return true;}return false;*/}
}

 (4)华为研发工程师编程题——字符集合

import java.util.Scanner;
public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (sc.hasNext()) {String str = sc.nextLine();StringBuilder sb = new StringBuilder();for (int i = 0; i < str.length(); i++) {char ch = str.charAt(i);if (!sb.toString().contains(ch + "")) {//contains里面只能是字符串序列,ch是单个字符,ch+""就变成了字符串sb.append(ch);}}System.out.println(sb.toString());}sc.close();}
}

相关文章:

【深入了解Java String类】

目录 String类 常用方法 字符串的不可变性 String的内存分析 StringBuilder类 解释可变和不可变字符串 常用方法 面试题&#xff1a;String&#xff0c;StringBuilder&#xff0c;StringBuffer之间的区别和联系 String类的OJ练习 String类 【1】直接使用&#xff0c…...

基于SpringBoot的知识管理系统

目录 前言 一、技术栈 二、系统功能介绍 用户管理 文章分类 资料分类 文章信息 论坛交流 资料下载 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#xff0c;针对这个问题开发一个…...

Pytorch基础:Tensor的reshape方法

在Pytorch中&#xff0c;reshape是Tensor的一个重要方法&#xff0c;它与Numpy中的reshape类似&#xff0c;用于返回一个改变了形状但数据和数据顺序和原来一致的新Tensor对象。注意&#xff1a;此时返回的数据对象并不一定是新的&#xff0c;这取决于应用此方法的Tensor是否是…...

【数据库——MySQL】(13)过程式对象程序设计——存储函数、错误处理以及事务管理

目录 1. 存储函数2. 存储函数的应用3. 错误处理4. 抛出异常5. 事务处理6. 事务隔离级7. 应用实例参考书籍 1. 存储函数 要 创建 存储函数&#xff0c;需要用到 CREATE 语句&#xff1a; CREATE FUNCTION 存储函数名([参数名 类型, ...])RETURNS 类型[存储函数体]注意&#xff1…...

Spring Boot的魔法:构建高性能Java应用

文章目录 Spring Boot&#xff1a;简化Java开发Spring Boot的性能优势1. 内嵌服务器2. 自动配置3. 起步依赖4. 缓存和优化5. 异步处理 实际示例&#xff1a;构建高性能的RESTful API总结 &#x1f389;欢迎来到架构设计专栏~Spring Boot的魔法&#xff1a;构建高性能Java应用 ☆…...

如何做好测试?(七)兼容性测试 (Compatibility Testing, CT)

1. 兼容性测试介绍 兼容性测试 (Compatibility Testing, CT)是一种软件测试方法&#xff0c;旨在验证应用程序在不同操作系统、浏览器、设备和网络环境下的正确运行和一致性。对于网上购物系统来说&#xff0c;兼容性测试非常重要&#xff0c;因为用户可能使用各种不同的设备和…...

经典循环神经网络(一)RNN及其在歌词数据集上的应用

经典循环神经网络(一)RNN及其在歌词数据集上的应用 1 RNN概述 在深度学习兴起之前&#xff0c;NLP领域一直是统计模型的天下&#xff0c;例如词对齐算法GIZA&#xff0c;统计机器翻译开源框架MOSES等等。在语言模型方向&#xff0c;n-gram是当时最为流行的语言模型方法。n-gr…...

docker+mysql+flask+redis+vue3+uwsgi+docker部署

首先拉取mysql的镜像&#xff0c;这里用的mysql5.7.6 docker pull mysql:5.7.6 镜像拉取完成后启动&#xff1a; docker run --name my-mysql -d -p 3306:3306 -v /usr/local/my-mysql/conf:/etc/mysql/conf.d -v /usr/local/my-mysql/data:/var/lib/mysql -e MYSQL_ROOT_PA…...

Spring boot接收zip包并获取其中excel文件的方法

1、问题 工作中遇到一个需求&#xff0c;接收一个zip包&#xff0c;读取其中的excel文件并处理&#xff0c;减少用户多次选择目录和文件的痛点&#xff0c;该zip包包含多级目录 2、依赖 需要用到apache的Workbook类来操作Excel&#xff0c;引入以下依赖 <dependency>&l…...

Ubuntu镜像源cn.arichinve.ubuntu.com不可用原因分析和解决

文章目录 Ubuntu查看系统版本Ubuntu更新系统不能更新Ubuntu查看APT更新源配置cn.archive.ubuntu.com已经自动跳转到清华镜像站Ubuntu变更镜像源地址备份原文件批量在VIM中变更 Ubuntu国内镜像站推荐推荐阅读 今天想要在Ubuntu环境下搭建一个测试环境&#xff0c;进入Ubuntu系统…...

Java基础面试,String,StringBuffer,StringBuilder区别以及使用场景

简单的几句 String是final修饰的&#xff0c;不可变&#xff0c;每次操作都会产生新的对象。StringBuffer和StringBuilder都是在原对象上进行操作StringBuffer是线程安全的&#xff0c;StringBuilder是线程不安全的。StringBuffer方法是被synchronized修饰的 所以在性能方面大…...

基于SpringBoot的高校学科竞赛平台

目录 前言 一、技术栈 二、系统功能介绍 竞赛题库管理 竞赛信息管理 晋级名单管理 往年成绩管理 参赛申请管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步…...

excel如何让线条消失,直接设置网格即可,碰到不方便的地方优先百度,再采取蛮干

怎么将excel表格中的隐形线条去掉...

抖音短视频seo矩阵系统源代码开发系统架构及功能解析

短视频seo源码&#xff0c;短视频seo矩阵系统底层框架上支持了从ai视频混剪&#xff0c;视频批量原创产出&#xff0c;云存储批量视频制作&#xff0c;账号矩阵&#xff0c;视频一键分发&#xff0c;站内实现关键词、短视频批量搜索排名&#xff0c;数据统计分类多功能细节深度…...

在pycharm中弹出图后,需要关闭才会显示Process finished with exit code 0

在pycharm中弹出图后&#xff0c;需要关闭才会显示Process finished with exit code 0 在PyCharm中&#xff0c;当你运行一个Python程序并弹出一个图形窗口时&#xff0c;程序会等到图形窗口关闭后才会显示 “Process finished with exit code 0” 的消息。 这是 由于代码执行…...

【计算机网络笔记六】应用层(三)HTTP 的 Cookie、缓存控制、代理服务、短连接和长连接

HTTP 的 Cookie HTTP 的 Cookie 机制要用到两个字段&#xff1a;响应头字段 Set-Cookie 和请求头字段 Cookie。 Cookie 可以设置多个 key-value 对&#xff0c; 响应头中可以设置多个 Set-Cookie 字段&#xff0c;请求头Cookie后面可以设置多个键值对&#xff0c;用分号隔开&a…...

Vue中的数据分页与分页组件设计

Vue中的数据分页与分页组件设计 在前端开发中&#xff0c;数据分页是一个常见的需求&#xff0c;特别是当处理大量数据时。Vue作为一款流行的JavaScript框架&#xff0c;提供了强大的工具和生态系统来实现数据分页。本文将介绍如何在Vue中进行数据分页&#xff0c;以及如何设计…...

TCP串流场景剖析

在TCP&#xff08;传输控制协议&#xff09;中&#xff0c;串流场景指的是数据通过TCP连接以流&#xff08;stream&#xff09;的方式传输。TCP是一种可靠的、面向连接的传输协议&#xff0c;它将数据切分为多个报文段&#xff0c;通过网络传输&#xff0c;并在接收端进行重组&…...

Windows历史版本下载

1、微PE工具箱&#xff08;非广告本人常用&#xff09; 常用安装Windows系统的微PE工具 地址&#xff1a;https://www.wepe.com.cn/download.html 2、Windows系统下载地址&#xff08;非微软官方&#xff09; 地址&#xff1a;MSDN, 我告诉你 - 做一个安静的工具站 下载&…...

企业级磁盘阵列存储系统由硬到软全析

企业级磁盘阵列是由一组设备构成的存储系统,主要包括两种类型的设备,分别是控制器和扩展柜,其中控制器只有一台,扩展柜可以没有,也可以有多台。在EMC的Unity中分别称为DPE(Disk Processor Enclosure)和DAE(Disk Array Enclosure),在华为的OceanStor里面称为控制框和硬…...

V4L2 驱动架构介绍

V4L2 简介 Video for Linux two(Video4Linux2)简称 V4L2&#xff0c;是 V4L 的改进版。V4L2 是 linux操作系统下用于视频和音频数据采集设备的驱动框架&#xff0c;为驱动和应用程序提供了一套统一的接口规范。 在 Linux 下&#xff0c;所有外设都被看成一种特殊的文件&#xf…...

掌握这些技巧,让Excel批量数据清洗变得简单高效!

什么是数据清洗 数据清洗是指在数据处理过程中对原始数据进行筛选、转换和修正&#xff0c;以确保数据的准确性、一致性和完整性的过程。它是数据预处理的一部分&#xff0c;旨在处理和纠正可能存在的错误、缺失值、异常值和不一致性等数据质量问题。 为什么要数据清洗 Exce…...

成都瀚网科技:抖音上线地方方言自动翻译功能

为了让很多方言的地域历史、文化、习俗能够以短视频的形式生产、传播和保存&#xff0c;解决方言难以被更多用户阅读和理解的问题&#xff0c;平台正式上线推出当地方言自动翻译功能。创作者可以利用该功能&#xff0c;将多个方言视频“一键”转换为普通话字幕供大众观看。 具体…...

【k8s】【docker】web项目的部署

yaml配置文件 后端&#xff1a;springboot项目 前端&#xff1a;vue项目&#xff0c;之前镜像封装的nginx.conf反向代理配置直接使用了docker-compose.yml中services的名称&#xff0c;无法代理成功&#xff0c;可修改为127.0.0.1 # 后端 apiVersion: apps/v1 kind: Deployment…...

【视频去噪】基于全变异正则化最小二乘反卷积是最标准的图像处理、视频去噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

国庆day3---网络编程知识点脑图整合

...

链表经典面试题(六)

判断链表是否有环 1.题目2.思路分析(文字)3.详细的注释和代码实现 1.题目 2.思路分析(文字) 3.详细的注释和代码实现 public class Solution {public boolean hasCycle(ListNode head) {//定义两个快慢指针ListNode fast head;ListNode slow head;//让快指针走两步,慢指针走…...

SM2签名算法中随机数K的随机性对算法安全的影响

一、构造如下SM2签名算法过程1 Sig1 r1 F2BFC778C66127C74E3613FAA1AB6E207059740B317597A78BBFCDF58AED0A51 Sig1 s1 4FC719D00334CCC23098036DEEAA71DB464A076EFA79283389D3414D70659E88 私钥d B3124DC843BB8BA61F035A7D0938251F5DD4CBFC…...

郁金香2021年游戏辅助技术中级班(六)

郁金香2021年游戏辅助技术中级班&#xff08;六&#xff09; 055-ce,xdbg调试分析接任务交任务完成任务056-C,C写代码测试接任务交任务完成任务我们再来分析一下完成任务 057-C,C写代码测试交任务完成任务 055-ce,xdbg调试分析接任务交任务完成任务 创建一个新角色&#xff0c…...

毛玻璃员工卡片悬停效果

效果展示 页面结构组成 通过效果展示图&#xff0c;我们可以看出页面布局比较常规&#xff0c;最核心的就是卡片&#xff0c;当鼠标没有悬停在卡片上时&#xff0c;文字和头像处于半透明状态&#xff0c;当鼠标悬停在卡片上是&#xff0c;底部会展示社交图标。 CSS 知识点 b…...

最新新闻热点事件2024年/优化百度seo

二叉树 满足树形结构每个节点最多有两个子节点&#xff0c;即左子树和右子树树是有序的&#xff0c;指的是&#xff0c;单左子树和单右子树是不一样的满二叉树 是二叉树每个非叶子结点都有两个子节点对于深度为k的二叉树&#xff0c;节点总数为2^k - 1完全二叉树 是二叉树如…...

互联网做网站的话术/seo的搜索排名影响因素有

unity是5.5&#xff0c;android studio是2.3.3 一&#xff1a;在android Studio导出aar插件到unity 说明一下aar与jar插件的区别&#xff1a;jar是只包含配置文件和class文件&#xff0c;而aar插件是包括资源的&#xff0c;两者都能用压缩软件打开。 首先打开as建立新的工程&a…...

网站公司用什么软件做网站/武汉今日新闻头条

题目 如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的, 我们姑且定义"距离"为两节点之间边的个数。 写一个程序, 求一棵二叉树中相距最远的两个节点之间的距离。解题思路 此问题可以分为2步 1.求根节点到左子树中的节点深度d1 2.求根节点到右子树中的节…...

哪些网站可以进行域名注册/新网站怎么做推广

这是信任的考验——靠人品代收货款致“跑路”频现并引发社会问题&#xff0c;有没有根治的法儿&#xff1f;如何让物流企业专注物流业务而不再盯着代收货款起歪主意&#xff1f;物流企业因挪用货款而跑路的“顽疾”&#xff0c;长期以来困扰着物流界&#xff0c;现在&#xff0…...

政府网站建设整改工作方案/营销软文300字

初识KNN KNN算法是《机器学习实践》这本书介绍的第一个分类算法&#xff0c;可见其地位非凡。虽然随着入行资历增长&#xff0c;可能会越来越看轻它&#xff0c;但这就是历练的必经之路&#xff0c;要想过此路&#xff0c;先得跨过它。 KNN&#xff08;K-NearestNeighbor&…...

无锡公司网站建设电话/杭州关键词排名系统

chatGPT已经爆火一段时间了&#xff0c;我想大多数的开发者都在默默的在开发和测试当中&#xff0c;可能也是因为这个原因所以现在很难找到关于开发中遇到的一些坑或者方法和技巧。为什么别人的机器人能联想之前的语料&#xff0c;而你的却像个每次都只如初见的高冷机器人&…...