一.StringBuffer
1.概述
- 引入,对于String来说,如果要对字符串作拼接,每次拼接都会建立一个新的String对象(常量池中),耗时间又浪费空间——StringBuffer
- 介绍
A: java.lang包,java.lang.StringBuffer
B:public final class StringBuffer---不能被继承
C:线程安全的可变字符序列,
安全:同步----互斥--数据安全---医院、银行网站
不安全:不同步---效率高---新闻网站、论坛
安全和效率问题一直是一个难题
D:类似于一个String字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容
2.构造方法
StringBuffer();//无参构造,初始容量为16
StringBuffer(int capacity);//指定容量
StringBuffer(String str);//容量为str.length()+16
public int capacity();//返回当前容量,理论值,超过容量需要再次分配
public int length();//返回长度(字符数),实际值
3.功能
A:添加功能
public StringBuffer append(String str);//把任意类型添加到字符串缓冲区,并返回本身
return this
public StringBuffer insert(int offset, String str);//在offset位置插入str
同样return this
B:删除功能
public StringBuffer deleteCharAt(int index);//删除指定位置的一个字符
return this
public StringBuffer delete(int start, int end);//左闭右开
return this
sb.delete(0, sb.length())//全删
C:替换功能
public StringBuffer replace(int start, int end, String str);//不包括end
return this
D:反转功能
public StringBuffer reverse();//反转
return this;
E:截取功能:返回的是String
public String substring(int start);//
public String substring(int start, int end);//不包括end
F:与String的转换功能
String转StringBuffer:
StringBuffer sb = new StringBuffer(s)
或
StringBuffer sb = new StringBuffer();
sb.append(s);
StringBuffer转String:
String s = new String(sb);
或
String s = sb.toString();
练习1
//数组拼接成一个字符串
public static String arrayToString2(int[] arr)
//静态方法可以直接类名或对象名调用,其它类内方法可以直接调用arrayToString2(arr),但编写代码时候别这样写,最好类名调用
{
StringBuffer sb = new StringBuffer();
for (int i = 0; i < arr.length; i++)
{
sb.append(arr[i]);
}
String s = sb.toString();
return s;
}
练习2
//字符串反转
public static String myReverse(String s)
{
StringBuffer sb = new StringBuffer(s);
return sb.reverse().toString();
}
练习3
//看一个字符串是否为对称字符串
public static boolean isSame(String s)
{
return new StringBuffer(s).reverse().toString().equals(s);
}
面试题
- StringBuilder:一个可变字符序列,提供一个和StringBuffer兼容的API,但不保证同步--不安全的
- String、StringBuffer、StringBuffer区别
A:String是内容不可变的,其他两个可变
B:StringBuffer同步的,数据安全,效率低;StringBuffer不同步,数据不安全,效率高 - StringBuffer和数组的区别
二者都可以看成一个装数据的容器,前者可以放任意类型的数据,最终都是一个字符串数据;而数组都是同一个数据 - String和StringBuffer分别作为参数传递
String是一种特殊的引用类型,它的参数传递和基本类型一样。
而StringBuffer放的是地址值
(首先要理解本质上void返回值实参地址指向不变,String运算只是改变形参地址指向,StringBuffer内置方法不改变地址指向,而改变指向的堆空间内容。常量池的值是不变的,函数中的s2是指向常量池中“worldworld”,只是指向地址变了,但对实参s2没有影响,他们是两个不同对象;而StringBuffer中实参s2和形参s2虽然同样是两个对象,但在堆内存指向同一内内容,形参s2改动会影响实参s2)
public static void change(StringBuffer sb1, StringBuffer sb2) {//地址492 493
sb1 = sb2;//地址493
sb2.append(sb1);////地址493
}
public static void change(String s1, String s2) {//地址488 489
s1 = s2;//地址489
s2 = s1 + s2;//地址491
}
public static void main(String[] args){
// int[] arr = {44, 33, 55, 11, 22};
// String s = finalTest.arrayToString2(arr);
String s1 = "hello";//地址488
String s2 = "world";//地址489
System.out.println(s1 + "---" + s2);// hello---world
change(s1, s2);
System.out.println(s1 + "---" + s2);// hello----world
StringBuffer sb1 = new StringBuffer("hello");//地址492
StringBuffer sb2 = new StringBuffer("world");//地址493
System.out.println(sb1 + "---" + sb2);// hello---world
change(sb1, sb2);
System.out.println(sb1 + "---" + sb2);//hello----worldworld
}
- 高级冒泡排序
冒泡排序:相邻元素两两比较,大的往后放,第一次完毕后,最大值出现在最大索引处,继续直到有序
public static void myBubbleSort(int[] arr)
{
for (int i = 0; i < arr.length -1; i++)
//一共有length -2次冒泡
for (int j = 0; j < arr.length-i-1; j++)
//ith次冒泡比较length-i-1次
{
if (arr[j] > arr[j+1])
{
int tempt = arr[j] ^ arr[j+1];
arr[j] = arr[j+1];
arr[j+1] = tempt ^ arr[j];
}
}
}
- 高级选择排序
从索引0开始,依次和后面元素比较,遇到小的交换位置,第一次完毕,最小值出现在了最小索引处
public static void mySelectedSort(int[] arr)
{
for (int i = 0; i < arr.length - 1; i++)
//共选择length-1轮
for (int j = i+1; j <= arr.length - 1; j++)
//ith比较length-i-1
{
if (arr[i] > arr[j])
{
int tempt = arr[i] ^ arr[j];
arr[i] = arr[j];
arr[j] = tempt ^ arr[i];
}
}
}
- 把字符串中字符排序
public static void myBubblecharSort(char[] arr)
{
for (int i = 0; i < arr.length -1; i++)//一共有length -2次冒泡
for (int j = 0; j < arr.length-i-1; j++)//ith次冒泡比较length-i-1次
{
if (arr[j] > arr[j+1])
{
char tempt = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tempt;
}
}
}
- 二分法查找
有序数组中,每次都和中间元素比较,然后选择左右
public static int myBinarySearch(int[] arr, int start, int end, int target)
{
if (arr[(end+start)/2] == target) return (end+start)/2;
if (start >= end) return -1;//为了防止用户输入id越界,用了>号
else if (arr[(end+start)/2] < target)
return myBinarySearch(arr, (end+start)/2 + 1 , end, target);
else
return myBinarySearch(arr, start, (end+start)/2 - 1, target);
}
二.Arrays类
1.概述
- java.util.Arrays extends Object;包含操作数组的各种方法,工具类(都是static方法)
public static String toString(任意类型[] a);
public static void sort(各种类型[] a);
public static int binarySearch(int[] a, int k);
//各种类型都可以,以int为例
2.源码解析
- sort底层是快速排序
- toString:
public static String toString(int[] a) {
if (a == null)//空数组
return "null";
int iMax = a.length - 1;
if (iMax == -1)//无元素数组
return "[]";
StringBuilder b = new StringBuilder();//基于StringBuffer实现
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();//转化为String
b.append(", ");
}
}
- 二分查找
public static int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
三.基本包装类型
1.引入
- 把基本数据类型封装为对象的好处在于可以在对象中定义更多功能方法来操作该数据
- 常用:基本数据类型与String间的转换
- Byte,Short,Integer,Long,Float,Double,Character,Boolean
- .MAX_VALUE, .MIN_VALUE(static int)
2.Integer(java.lang.Integer)
A:构造方法
Integer在对象中包装了一个基本类型int的值,也提供了多种方法,int和Stirng的转换,和一些常用的常量
Integer(int value);//由基本类型int转变为引用类型
Integer(String s);//String转Integer
注意,s必须为数字字符组成
B:成员方法
Integer.valueOf(num)//int---Integer
Num.intValue()//Integer---int
a:int类型和String类型相互转换
int----String
String.valueOf(num);
String---int
static int Integer.parseInt(s);
b:进制转换
* 常用的基本进制转换
* public static String toBinaryString(int i)
* public static String toOctalString(int i)
* public static String toHexString(int i)
*
* 十进制到其他进制
* public static String toString(int i,int radix)
* 由这个我们也看到了进制的范围:2-36
* 为什么呢?0,...9,a...z
*
* 其他进制到十进制
* public static int parseInt(String s,int radix)
C:自动拆箱和装箱
* JDK5的新特性
* 自动装箱:把基本类型转换为包装类类型
* 自动拆箱:把包装类类型转换为基本类型
*
* 注意一个小问题:
* 在使用时,Integer x = null;代码就会出现NullPointerException。
* 建议先判断是否为null,然后再使用。
Integer ii = 100;
ii += 200;
System.out.println("ii:" + ii);
// 通过反编译后的代码
Integer ii = Integer.valueOf(100); //自动装箱
ii = Integer.valueOf(ii.intValue() + 200); //自动拆箱,再自动装箱
System.out.println((new StringBuilder("ii:")).append(ii).toString());
D:面试题
包装类型有缓冲池
private static class IntegerCache
以Integer为例,针对-128到127之间的数据直接赋值,如果在该范围,每次不创建新空间,只是指向该数组中的该地址
Integer i = 1//自动装箱Integer.valueOf(1)
i += 1 //自动拆箱再装箱
//ii = Integer.valueOf(ii.intValue() + 1)
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2);//f 地址
System.out.println(i1.equals(i2));//t
System.out.println("-----------");
Integer i3 = new Integer(128);
Integer i4 = new Integer(128);
System.out.println(i3 == i4);//f
System.out.println(i3.equals(i4));//t
System.out.println("-----------");
Integer i5 = 128;
Integer i6 = 128;//超过127直接new开辟堆空间
System.out.println(i5 == i6);//f
System.out.println(i5.equals(i6));//t
System.out.println("-----------");
Integer i7 = 127;
Integer i8 = 127;
System.out.println(i7 == i8);//t
System.out.println(i7.equals(i8));//t
装箱中的valueOf方法
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);//给缓冲数组赋值
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
3.character类
- 概述:java.lang.Character;包装基本类型char的值,提供一些方法,同样重写了输出,println数组内容而不是地址
- 构造方法:
Character(char value); - 常见方法
* public static boolean isUpperCase(char ch):判断给定的字符是否是大写字符
* public static boolean isLowerCase(char ch):判断给定的字符是否是小写字符
* public static boolean isDigit(char ch):判断给定的字符是否是数字字符
* public static char toUpperCase(char ch):把给定的字符转换为大写字符
* public static char toLowerCase(char ch):把给定的字符转换为小写字符
- 统计一个字符串中大写字母字符,小写字母字符和数字字符的出现次数
public static int[] myCharCount(String s)
{
char[] s_arr = s.toCharArray();//先转字符数组
int upperCases = 0;
int lowerCases = 0;
int digitCases = 0;
for (int i = 0; i < s_arr.length; i++)
{
if(Character.isDigit(s_arr[i]))
digitCases++;
else if(Character.isUpperCase(s_arr[i]))
upperCases++;
else if(Character.isLowerCase(s_arr[i]))
lowerCases++;
else
continue;;
}
int[] arr = {upperCases, lowerCases, digitCases};
return arr;
}