线程的安全问题:线程安全 ==> 是同步的 ==> 但是执行效率低 ==> 银行系统,医疗平台;
线程不安全 ==> 是不同步的 ==> 但是执行效率高 ==> 新闻网站,论坛;
面试题:
StringBuffer和String的区别?
前者是一个可变的字符序列,后者是不可变的字符序列;
如果从内存角度考虑,String定义的时候,会在会在常量池中开辟空间,比较耗费内存;
而StringBuffer是在字符缓冲区里它所定义的字符,结束程序时,会释被放掉;
StringBuffer的构造方法:
StringBuffer():无参构造的形式,初始容量16;
StringBuffer(int capacity):指定容量构造一个字符串缓冲区;
StringBuffer(String str):构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容;
StringBuffer的获取功能:
public int length():返回长度;
public int capacity():返回当前容量 (如果超过容量,系统自动分配(存储字符串的时候,英文的));
举例:
public class StringBufferDemo {
public static void main(String[] args) {
//StringBuffer() :无参构造的形式,初始容量16
//创建一个字符串缓冲区
StringBuffer sb = new StringBuffer() ; //实际开发中,默认无参构造
System.out.println("sb:"+sb);//:当前缓冲区没有字符序列...
System.out.println("length():"+sb.length());
System.out.println("capacity():"+sb.capacity());
System.out.println("------------------------");
//StringBuffer(int capacity) :指定容量构造一个字符串缓冲区
StringBuffer sb2 = new StringBuffer(50) ;
System.out.println("length():"+sb2.length());
System.out.println("capacity():"+sb2.capacity());
System.out.println("------------------------");
//StringBuffer(String str) 构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容
StringBuffer sb3 = new StringBuffer("hello");
System.out.println("sb3:"+sb3);
System.out.println("length():"+sb3.length());
System.out.println("capacity():"+sb3.capacity());//初始容量+当前字符数
//StringBuffer sb4 = "hello" ; 不能直接转换(不能直接将一个字符串类赋值给一个对象类型 StringBuffer)
}
}
StringBuffer的添加功能:
public StringBuffer append(String/boolean....):在字符串缓冲区中追加数据(在末尾追加),并且返回字符串缓冲区本身(实际开发中用的多);
public StringBuffer insert(int offset,String str):将当前str字符串添加到指定位置处,它返回字符串缓冲区本身;
举例:
public class StringBufferDemo2 {
public static void main(String[] args) {
//创建一个字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
//public StringBuffer append(String/boolean....)
StringBuffer sb2 = sb.append("hello") ;
System.out.println("sb:"+sb);
System.out.println("sb2:"+sb2);
System.out.println(sb==sb2);
System.out.println("---------------------------");
//直接追加功能
sb.append("hello") ;
sb.append('A');
sb.append(true);
sb.append(100);
sb.append("world") ;
sb.append(3.14) ;
System.out.println("sb:"+sb);
System.out.println("---------------------------");
//链式编程
StringBuffer sb1=new StringBuffer();
sb1=sb1.append("hello").append(100).append('a').append(true);
System.out.println("sb1:"+sb1);
System.out.println("---------------------------");
//public StringBuffer insert(int offset,String str)将当前str字符串添加到指定位置处,它返回字符串缓冲区本身
sb.insert(5, "JavaSE");
System.out.println("sb:"+sb); //从下标为5的的元素开始添加
}
}
StringBuffer的删除功能:
public StringBuffer deleteCharAt(int index):移除指定位置处的字符;
public StringBuffer delete(int start,int end):移除从指定位置处到end-1处的子字符串;
举例:
public class StringBufferDemo3 {
public static void main(String[] args) {
//创建字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
//追加
sb.append("hello");
sb.append("world");
sb.append("java");
System.out.println("sb:"+sb);
//需求:移除'e'这个字符
//public StringBuffer deleteCharAt(int index):移除指定位置处的字符
sb.deleteCharAt(1);
System.out.println("sb:"+sb);
//需求:移除第一个'l'这个字符
sb.deleteCharAt(1);
System.out.println("sb:"+sb);
//public StringBuffer delete(int start,int end):移除从指定位置处到end-1处的子字符串
//需求:移除world
sb.delete(5, 10); //[5,10) ==> 5,6,7,8,9 五个字符
System.out.println("sb:"+sb);
}
}
StringBuffer的反转功能:
public StringBuffer reverse():将缓冲区中的字符序列反转取代,返回它(字符串冲)本身;
举例:
public class StringBufferDemo4 {
public static void main(String[] args) {
//创建字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
//添加
sb.append("圆圆高爱我") ;
System.out.println("sb:"+sb);
//开始反转
sb.reverse() ;
System.out.println("sb:"+sb);
}
}
StringBuffer的截取功能:
public String substring(int start):从指定位置开始截取,默认截取到末尾,返回值不再是缓冲区本身,而是一个新的字符串;
public String substring(int start,int end):从指定位置开始到指定位置结束,包前不包后,返回值不再是缓冲区本身,而是一个新的字符串;
举例:
public class StringBufferDemo5 {
public static void main(String[] args) {
//创建StringBuffer对象
StringBuffer sb = new StringBuffer() ;
//添加
sb.append("hello");
sb.append("world");
sb.append("java");
sb.append("JavaWeb") ;
System.out.println("sb:"+sb); //helloworldjavaJavaWeb
//public String substring(int start):
String str = sb.substring(5) ; //从下标为5开始截取一直到末尾
System.out.println("str:"+str); //worldjavaJavaWeb
System.out.println("------------------------");
//public String substring(int start,int end)
String str2 = sb.substring(5, 10) ; //从下标为5开始到下标为10之前(不包括10)
System.out.println("str2:"+str2);//world 返回的是被截取的字符串
}
}
StringBuffer的替换功能:
public StringBuffer replace(int start,int end,String str):从开始位置到指定位置,用新的字符串str替换,返回值是字符串缓冲区本身;
举例:
public class StringBufferDemo6 {
public static void main(String[] args) {
//创建字符串缓冲区对象
StringBuffer sb = new StringBuffer();
//添加
sb.append("hello") ;
sb.append("world") ;
sb.append("java") ;
System.out.println("sb:"+sb); //hellowoeldjava
//public StringBuffer replace(int start,int end,String str)
sb.replace(5, 10,"生日快乐") ;
System.out.println("sb:"+sb); //hello生日快乐java
}
}
String 和 StringBuffer 之间的相互转换:
原因:String可能会需要用StringBuffer的功能,StringBuffer也可能需要用到String的功能,所以需要相互转换;
举例:
public class StringBufferTest {
public static void main(String[] args) {
//String---StringBuffer
//定义了一个
String s = "hello";
//StringBuffer sb = s ; //会报错,不能直接将String的值赋给StringBuffer
//StringBuffer sb = "hello"; //也会报错
// 方式1 :带参构造,StringBuffer(String str)
StringBuffer sb = new StringBuffer(s) ;
//方式2:可以通过无参构造创建字符串缓冲区对象,给缓冲区中追加内容
StringBuffer sb2 = new StringBuffer() ;
sb2.append(s) ;
System.out.println("sb:"+sb); //hello
System.out.println("sb2:"+sb2); //hello
System.out.println("----------------------------");
//StringBuffer---String
StringBuffer buffer = new StringBuffer("world") ;
//方式1:public String(StringBuffer buffer)分配一个新的字符串,它包含字符串缓冲区参数中当前包含的字符序列
String str = new String(buffer) ;
//方式2:StringBuffer的功能:public String toString()返回此序列中数据的字符串表示形式
String str2 = buffer.toString() ;
System.out.println("str:"+str); //world
System.out.println("str2:"+str2); //world
}
}
例题:
package org.westos.a_stringbuffer;
/**
*需求:有一个数组:需要将数组 拼接成字符串类型
* 举例
* int[] arr = {1,2,3};
* 结果:[1,2,3]
*/
public class StringBufferTest2 {
public static void main(String[] args) {
//定义一个数组
int[] arr = {1, 2, 3} ;
//方式String类型的方式:
String str = arrayToString(arr) ;
System.out.println("str:"+str);
//方式2:StringBuffer进行实现
String str2 = arrayToString2(arr) ;
System.out.println("str2:"+str2);
}
//方式2
public static String arrayToString2(int[] arr) {
//创建字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
//追加左中括号
sb.append("[") ;
//遍历数组
for(int x = 0 ;x < arr.length ; x ++) {
//判断
if(x==arr.length-1) {
sb.append(arr[x]);
}else {
sb.append(arr[x]).append(", ") ;
}
}
sb.append("]") ;
return sb.toString() ;
}
//方式1:利用字符串拼接
public static String arrayToString(int[] arr) {
//定义一个字符串:
String result = "" ;
//拼接左中括号
result += "[" ;
//遍历数组
for(int x = 0 ; x < arr.length; x ++) {
//判断
if(x==arr.length-1) {
result += arr[x] ;
result += "]" ;
}else {
result += arr[x] ;
result += ", " ;
}
}
return result ;
}
}
例题:
package org.westos.a_stringbuffer;
import java.util.Scanner;
/**
* 判断一个字符串是否是对称字符串(方法改进)
*
* 例如"abc"不是对称字符串,"aba"、"abba"、"aaa"、"mnanm"是对称字符串
* 分析:
* 用键盘录入改进
* 字符串中的第一个字符和最后一个字符比较
* 用第二个和倒数第二个...
*
* ......
* 比较的长度length/2
*
*/
public class StringBufferTest3 {
public static void main(String[] args) {
//创建键盘录入对象:
Scanner sc = new Scanner(System.in) ;
//接收数据
System.out.println("请输入一个字符串:");
String line = sc.nextLine() ;
//用方法改进
boolean flag = isSame(line) ;
System.out.println("flag:"+flag);
}
//StringBuffer
public static boolean isSame(String s) {
//创建字符串缓冲区对象
StringBuffer sb = new StringBuffer(s) ;
//反转
String str = sb.reverse().toString() ;
return str.equals(s) ;
//一步完成
//return new StringBuffer(s).reverse().toString().equals(s);
}
}
几个面试题:
1. StringBuffer,String,StringBuilder的区别?
StringBuffer和StringBuilder都是一个可变的字符序列,提供一个缓冲区.(两者都看做容器)
StringBuffer:线程安全的,同步的,执行效率低
StringBuilder:线程不安全的,不同步的,执行效率高,并且单线程中优先采用StringBuilder
StringBuffer 执行效率虽然低,但是由于String类型,并且他可变的字符序列,提供了缓冲区
2. StringBuffer和数组的区别?
数组:它是可以存储多个数据的容器,并且多个数据的类型必须一致
数组长度功能:length属性
StringBuffer:它是容器,它在缓冲区始终存储的只能字符串类型的数据
获取缓冲区的长度:length()
Integer类:是int类型的包装类类型;
Integer提供的静态功能:
public static String toBinaryString(int i); 输出int类型包装类的二进制形式;
public static String toOctalString(int i); 输出int类型包装类的八进制形式;
public static String toHexString(int i); 输出int类型包装类的十六进制形式;
获取Integer的最值:
public static final int MAX_VALUE; 可以取到的最大值;
public static final int MIN_VALUE; 可以取到的最小值;
其他类型的包装类:
基本类型对应都有一个包装类型,目的就为了将基本数据类型可以和String类型之间进行互相转换;
byte Byte
short Short
int Integer (重点) 只有int和char与其包装类差别较大,
long Long 其他的都只是首字母变为大写;
float Float
double Double
char character (重点)
Boolean Boolean
举例:
public class IntegerDemo {
public static void main(String[] args) {
System.out.println(Integer.toBinaryString(100)); //二进制组成:有0和1组成
System.out.println(Integer.toOctalString(100)); //组成规则:以0开头 0144
System.out.println(Integer.toHexString(100)); //组成规则:0x开头 0-9,a-f
System.out.println("-----------------------");
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
}
}
Integer的构造方法:
public Integer(int value);
public Integer(String s);
举例:
public class IntegerDemo2 {
public static void main(String[] args) {
//创建一个Integer类对象
Integer i = new Integer(100);
Integer ii = 100 ; //底层实际代码执行的是:valueOf(int i) :该类中本身有一缓冲区的 :缓冲的值的范围:-128~127
System.out.println("i:"+i); //100
System.out.println("ii:"+ii); //100
System.out.println("-----------------");
//public Integer(String s)
Integer iii = new Integer('a') ;
System.out.println("iii:"+iii); //97
Integer iiii = new Integer("100");
System.out.println("iiii:"+iiii);
Integer iiiii = new Integer("AA"); //这个功能输入的字符串必须是数字字符串;
System.out.println("iiiii:"+iiiii);//java.lang.NumberFormatException:数字格式化异常;
//int---String
//String---int
}
}
将int转换为String类型:
valueOf(int i) ;
将String转换为int类型:
static int parseInt(String s);
举例:
public class IntegerDemo3 {
public static void main(String[] args) {
//int---->String
//定义一个int类型的变量
int num = 100 ;
//方式1: 字符串拼接
String str = "" + num ;
System.out.println("str:"+str);
//方式2:valueOf(int i) ;
//int -->Integer--->String
Integer i = Integer.valueOf(num) ;
String str2 = i.toString() ;
System.out.println("str2:"+str2);
//方式3:静态toString(int i): static String toString(int i )
String str3 = Integer.toString(num) ;
System.out.println("str3:"+str3);
System.out.println("----------------------");
//String--->int
String s = "100";
//方式1:String-->integer--->int
Integer ii = new Integer(s);
//public int intValue()
int num2 = ii.intValue() ;
System.out.println("num2:"+num2);
//方式2:(常用)public static int parseInt(String s)
int num3 = Integer.parseInt(s) ;
System.out.println("num3:"+num3);
}
}
自动拆装箱:JDK5之后才有的特性;
可以将Integer--> 拆箱 int类型;
可以将int类型---> 装箱 Integer类型;
public class IntegerDemo4 {
public static void main(String[] args) {
//创建Integer对象
//Integer i = new Integer(100) ;
Integer i = 100 ;
i += 200; //先拆箱(Integer-->int),后装箱(int值---->Integer)
//引用类型 += 基本类型
System.out.println("i:"+i);
/**
* 反编译代码:
Integer i = Integer.valueOf(100);
i = Integer.valueOf(i.intValue() + 200);//(int类型的100 +200) 先拆成int在包装成Integer
System.out.println((new StringBuilder("i:")).append(i).toString());
*/
}
}
Character类: 在对象中包装一个基本类型 char 的值。Character 类型的对象包含类型为 char 的单个字段;
以确定字符的类别(小写字母,数字,等等);
构造方法:
public Character(char value);
举例:
public class CharacterDemo {
public static void main(String[] args) {
//创建Character类对象
Character ch1 = new Character((char)97) ;
Character ch2 = new Character('a') ;
System.out.println("ch1:"+ch1); //a
System.out.println("ch2:"+ch2); //a
}
}
Character类的判断功能:
public static boolean isDigit(char ch):确定指定字符是否为数字;
public static boolean isLowerCase(int ch):确定是否是小写字母字符;
public static boolean isUpperCase(int ch):确定是否大写字母字符;
两个转换功能:
public static int toLowerCase(int codePoint);
public static int toUpperCase(int codePoint);
举例:
public class CharacterDemo2 {
public static void main(String[] args) {
//测试Character类:
//public static boolean isDigit(char ch)确定指定字符是否为数字。
System.out.println("isDigit():"+Character.isDigit('A'));
System.out.println("isDigit():"+Character.isDigit('a'));
System.out.println("isDigit():"+Character.isDigit('0'));
System.out.println("---------------------------------");
//public static boolean isUpperCase(int ch):确定是否大写字母字符
System.out.println("isDigit():"+Character.isUpperCase('A'));
System.out.println("isDigit():"+Character.isUpperCase('a'));
System.out.println("isDigit():"+Character.isUpperCase('0'));
System.out.println("---------------------------------");
//public static boolean isLowerCase(int ch): 确定是否是小写字母字符
System.out.println("isDigit():"+Character.isLowerCase('A'));
System.out.println("isDigit():"+Character.isLowerCase('a'));
System.out.println("isDigit():"+Character.isLowerCase('0'));
System.out.println("---------------------------------");
//字符串的大小写转换
String s="JavaLove";
String s1=s.toUpperCase();
String s2=s.toLowerCase();
System.out.println("toUpperCase:"+s1); //JAVALOVE
System.out.println("toLowerCase:"+s2); //javalove
}
}
综合例题:
package org.westos.c_character;
import java.util.Scanner;
/**
*需求:键盘录入一个字符串,统计当前字符串中大写字母字符,小写字母字符,数字字符的个数(不考虑其他字符)
*
* 现在改进:直接Charater类的这三个判断功能
*/
public class CharacterDemo3 {
public static void main(String[] args) {
//定义三个统计变量
int bigCount = 0 ;
int smallCount= 0 ;
int numberCount = 0 ;
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//接收数据
System.out.println("请输入一个字符串:");
String line = sc.nextLine() ;
//把字符串转成字符数组
char[] chs = line.toCharArray() ;
//遍历,取出每一个字符
for(int x = 0 ; x < chs.length ; x ++) {
char ch = chs[x] ;
//判断当前ch字符是否为大写字母字符,数字字符,小写字母字符
if(Character.isUpperCase(ch)) {
bigCount ++;
}else if(Character.isDigit(ch)) {
numberCount++;
}else if(Character.isLowerCase(ch)) {
smallCount++ ;
}
}
System.out.println("大写字母字符有:"+bigCount+"个");
System.out.println("小写字母字符有:"+smallCount+"个");
System.out.println("数字字符有:"+numberCount+"个");
}
}
简单排序:
冒泡排序:两两比较,大的往后放,第一次比较完毕最大值出现在最大索引处;
冒泡排序思想:
代码实现:
package org.westos.d_array;
/**
* 冒泡排序: 两两比较,大的往后放,第一次比较完毕最大值出现在最大索引处....
*
*/
public class ArrayDemo {
public static void main(String[] args) {
// 定义一个数组,静态初始化
int[] arr = { 24, 69, 80, 57, 13 };
// 排序之前
System.out.println("排序前:");
//输出排序前的数组
printArray(arr);
System.out.println("----------------------");
System.out.println("排序后:");
bubboleSort(arr);
printArray(arr);
}
//方法实现数组排序
public static void bubboleSort(int[] arr) {
for (int x = 0; x < arr.length - 1; x++) {
for (int y = 0; y < arr.length - 1 - x; y++) {
if (arr[y] > arr[y + 1]) {
int temp = arr[y];
arr[y] = arr[y + 1];
arr[y + 1] = temp;
}
}
}
}
// 遍历功能
public static void printArray(int[] arr) {
System.out.print("[");
for (int x = 0; x < arr.length; x++) {
if (x == arr.length - 1) {
System.out.println(arr[x] + "]");
} else {
System.out.print(arr[x] + ", ");
}
}
}
}
选择排序:从0索引开始将对应的元素依次与后面的元素进行比较,然后1索引知道最后一个索引;
选择排序思想:
代码实现:
package org.westos.d_array;
/**
* 选择排序: 从0索引开始将对应的元素依次与后面的元素进行比较,然后1索引知道最后一个索引,小的数据往前方法,就可以得到一个排好序的数组...
*/
public class ArrayDemo2 {
public static void main(String[] args) {
// 定义数组
int[] arr = { 24, 69, 80, 57, 13 };
// 遍历功能
System.out.println("排序前:");
printArray(arr);
System.out.println("排序后:");
selectSort(arr); //用方法实现选择排序
printArray(arr); //输出排序好的数组
}
// 选择排序的功能
public static void selectSort(int[] arr) {
for (int x = 0; x < arr.length - 1; x++) {
for (int y = x + 1; y < arr.length; y++) {
if (arr[x] > arr[y]) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
}
}
}
//输出排序好的数组
public static void printArray(int[] arr) {
System.out.print("[");
for (int x = 0; x < arr.length; x++) {
if (x == arr.length - 1) {
System.out.println(arr[x] + "]");
} else {
System.out.print(arr[x] + ", ");
}
}
}
}
简单查找:
二分查找:将数组的区间每次减少整个数组的长度,直到只剩最后一个元素为需要查找的值;
折半查找思想:
代码实现:
package org.westos.d_array;
import javax.sql.rowset.serial.SerialArray;
/**
* 数组中的元素查找法(基本查找法)
*
* 折半查找(二分查找) :数组一定是有序
*分析:
* A:定义最小索引和最大索引
* B:计算中间索引
* C:中间索引对应的元素和需要查找的元素比较
* 相等,直接返回中间索引
* 不相等:
* 大了,左边找
* max = mid -1 ;
* 小了,右边找
* min = mid + 1 ;
* E:重新计算中间索引 ,回到B继续查找
*/
public class ArrayDemo3 {
public static void main(String[] args) {
//定义一个数组
int[] arr = {11,22,33,44,55,66,77} ;
//写一个方法来调用
int index = search(arr, 33) ;
System.out.println("index:"+index);
int index2 = search(arr, 333) ;
System.out.println("index2:"+index2);
}
/**
* 两个明确:
* 明确返回值类型:int
* 明确参数类型:2个参数 int[] arr ,int value
*/
public static int search(int[] arr,int value) {
//1定义数组中的最小索引和最大索引
int min = 0 ;
int max = arr.length -1 ;
//2 计算出中间索引
int mid = (max+min)/2 ;
//3)拿中间索引对应的元素和需要查找的元素进行比较
//如果相等,返回
while(arr[mid]!=value) {
//不相等
if(arr[mid] >value) {
max = mid -1 ;
}else {
min = mid + 1 ;
}
//如果这value在数组中找不到,找不到返回-1
if(min>max) {
return -1 ;
}
//重新计算出中间索引
mid = (max+min)/2 ;
}
return mid ;
}
}
综合例题:
package org.westos.d_array;
import java.util.Arrays;
import java.util.Scanner;
/**
* 把字符串中的字符进行排序。
* 举例:"dacgebf"
* 结果:"abcdefg"
*
* 分析:
* 1)键盘录入一个字符串"dacgebf"
* 2)可以将字符串转换成字符数组
* 3)冒泡排序
* 4)最终要字符串类型的数据
*
*/
public class ArrayTest {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//接收数据
System.out.println("请输入一个字符串:");
String line = sc.nextLine() ;
//将字符串转换成字符数组
char[] chs = line.toCharArray() ;
//排序
bobbleSort(chs);
//需要的是字符串类型
String result = Arrays.toString(chs) ;
System.out.println("result:"+result);
}
//冒泡排序
public static void bobbleSort(char[] chs) {
for(int x = 0 ;x < chs.length - 1; x ++) {
for(int y = 0 ; y < chs.length-1-x ; y++) {
if(chs[y]>chs[y+1]) {
char temp = chs[y] ;
chs[y] = chs[y+1] ;
chs[y+1] = temp ;
}
}
}
}
}