一.StringBuffer和StringBuilder
1.来源
字符串广泛应用在Java 编程中,在 Java中字符串属于对象,Java 提供了String 类来创建和操作字符串。但是String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,这样不仅效率低下,而且大量浪费有限的内存空间。所以就引入了两个新的类——StringBuffer类和StringBuild类。
2.使用
(1)构造方法
public StringBuffer(): 无参构造方法
public StringBuffer(int capacity): 指定容量的字符串缓冲区对象
public StringBuffer(String str): 指定字符串内容的字符串缓冲区对象StringBuffer的方法:
public int capacity():返回当前容量。 理论值
public int length():返回长度(字符数)。 实际值
(2)添加,删除,替换和反转功能
- public StringBuffer append(String str): 可以把任意类型数据添加到字符串缓冲区里面,并返回字符串缓冲区本身
- public StringBuffer insert(int offset,String str): 在指定位置把任意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身
- public StringBuffer deleteCharAt(int index): 删除指定位置的字符,并返回本身
- public StringBuffer delete(int start,int end): 删除从指定位置开始指定位置结束的内容,并返回本身
- public StringBuffer replace(int start,int end,String str): 从start开始到end用str替换
- public StringBuffer reverse(): 字符串反转
(3)截取功能
- public String substring(int start): 从指定位置截取到末尾
- public String substring(int start,int end): 截取从指定位置开始到结束位置,包括开始位置,不包括结束位置
//截取功能注意事项:这个方法的返回值值类型不再是StringBuffer本身,而是字符串类型。
(4)StringBuffer和String之间互相转换
- String——StringBuffer
- 通过构造方法:StringBuffer(String str)
- 通过append()方法
- StringBuffer——String
- 通过构造方法:String(StringBuffer buffer)
- 使用substring()方法
- 使用toString()方法
(5)案例演示
//把数组中的的数据按照指定格式拼成一个字符串
package com.westo.demo1;
public class MyTest8 {
public static void main(String[] args) {
int arr[]={1,2,3,4};
String str="[";
StringBuffer stringBuffer = new StringBuffer(str);
for (int i = 0; i < arr.length; i++) {
if(i==arr.length-1){
stringBuffer.append(arr[i]).append("]");
}else{
stringBuffer.append(arr[i]).append(",");
}
}
String s = stringBuffer.toString();
System.out.println(s);
}
}
//将字符串反转
package com.westo.demo1;
import java.util.Scanner;
public class MyTest9 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("输入一个字符串");
String s = scanner.nextLine();
StringBuffer stringBuffer = new StringBuffer(s);
System.out.println(stringBuffer.reverse());
}
}
(6)StringBuffer和StringBuilder的区别
- 相同点:StringBuffer和StringBuilder非常类似,均代表可变的字符序列,而且方法也一样。
- 区别:StringBuffer是多线程操作字符串,而StringBuilder是单线程操作字符串。
- 总结:所以StringBuffer在操作字符串上效率高,但安全性低。StringBuilder操作字符串时效率低,但安全性高。
(7)注意
- StringBuffer类中并没有重写equals()方法。所以:
package com.westo.demo1;
class Demo {
public static void main (String[] args) {
StringBuffer buffer1 = new StringBuffer("String");
StringBuffer buffer2 = new StringBuffer("String");
if ( buffer1.equals(buffer2) ) {
System.out.println("True");
} else {
System.out.println("False");
}
}
}
//结果是:False
二.数组的常见操作
1.二分查找
二分查找只对已经排好序的数组有用
(1)思想
- 二分查找的基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x.
- 实现:给数组的头和尾设置一个标记,比如i=0;j=a.length-1,mid=(i+j)/2。如果x<a[mid],j=mid;如果x>a[mid],i=mid;然后重新计算mid1的值。
- 用循环和递归都可以实现
(2)代码实现
package com.westmo.demo2;
import java.util.Scanner;
public class Search {
public static void main(String[] args) {
int arr[] = {1, 2, 3, 4, 5, 6};
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要查找的数");
int i = scanner.nextInt();
System.out.println(search(arr, i));
}
private static int search(int[] arr, int i) {
int start = 0, end = arr.length - 1;
int mid = (start + end) / 2;
while (start <= end) {
if(i==arr[mid]){
return mid;
}else if(i>arr[mid]){
start=mid;
}else if(i<arr[mid])
end=mid;
mid=(start+end)/2;
}
return -1;
}
}
2.数组的其他排序方式
关于其他的排序方法(冒泡,快速,选择,插入,堆,希尔等)笔者博客中有专门的介绍。
三.Arrays
1.概述
- Arrays是针对数组进行操作的工具类
- 提供了排序,查找等功能
2.用法
- public static String toString(int[] a)
- public static void sort(int[] a)
- public static int binarySearch(int[] a,int key)
- static boolean equals(int[] a, int[] a2) 比较两个数组中的元素,是否一样
- static int[] copyOf(int[] original, int newLength) 复制旧数组中的元素到一个新的数组中,新的数组长度是newLength 从0开始复制旧数组
- static int[] copyOfRange(int[] original, int from, int to) 复制旧数组中的指定范围间的几个元素到新数组中
案例演示
package com.westmo.demo2;
import java.util.Arrays;
public class MyTest1 {
public static void main(String[] args) {
int arr[]={23,56,12,3,45,48,9};
Arrays.sort(arr);//排序
System.out.println(Arrays.toString(arr));//输出打印
int i = Arrays.binarySearch(arr, 56);/查找元素56在数组中的索引位置
System.out.println(i);
}
}
Arrays类中的toString()方法和binarySearch()方法源码解析
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(", ");
}
}
//可以看出binarySearch()方法采用的是二分查找的方法。
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.概述
- Java中为了对基本数据类型进行更多,更方便的操作(比如将一个数转换为想要的进制),就提供了针对每一种基本数据类型提供了对应的类类型。
- 基本类型和包装类类型的对应
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
2.以Interger类为例介绍包装类的用法
(1)概述
- Integer 类在对象中包装了一个基本类型 int 的值,
该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,
还提供了处理 int 类型时非常有用的其他一些常量和方法 - public Integer(int value)
- public Integer(String s) //要个一个字面上是数字的字符串,如果不是就会报错
(2)String类型和int类型相互转换
int -- String
a:和""进行拼接
b:public static String valueOf(int i)
c:int -- Integer -- String
d:public static String toString(int i)
String -- int
a:String -- Integer -- intValue();
b:public static int parseInt(String s)
案例演示
package com.westmo.demo2;
public class MyTest2 {
public static void main(String[] args) {
//int转为String
int s=10;
String s1 = s + "";
String s2 = new String().valueOf(s);
Integer integer = new Integer(s);
String s3 = integer.toString(s);
//String转为int
String t="10";
Integer integer1 = new Integer(t);
int t1 = integer1.intValue();
int t2= Integer.parseInt(t);
}
}
3.自动装箱和拆箱
(1)概念
- 自动装箱:把基本数据类型转换为包装类类型
- 自动拆箱:把包装类类型转换为基本类型
(2)示例
Integer i=100;//自动装箱
i+=200;//自动拆箱
4.面试题
package com.westmo.demo2;
public class MyTest3 {
public static void main(String[] args) {
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2);//false
System.out.println(i1.equals(i2));//true
Integer i3 = new Integer(128);
Integer i4 = new Integer(128);
System.out.println(i3 == i4);//false 创建新的对象,所以地址值肯定不同
System.out.println(i3.equals(i4));//true
Integer i5 = 128;
Integer i6 = 128;
System.out.println(i5 == i6);//它没有创建新的对象,为什么还是false呢?
System.out.println(i5.equals(i6));//true
Integer i7 = 127;
Integer i8 = 127;
System.out.println(i7 == i8);//true
System.out.println(i7.equals(i8));//true
}
}
new Integer()这种情况就不再说了,就讨论以下Integer x=…,的情况
- Integer在与Integer比较的时候,由于直接赋值的时候会进行自动装箱,那么这里就要注意两个问题:
- 当要赋的这个值是-128<=x<=127之间的数时,将会直接缓存在IntegerCache中,那么赋值的时候,就不会创建新的Integer对象,而是从缓存中获取已经创建好的Integer对象。
- 当要赋的这个值不在这个范围时,就会直接new一个Integer对象。
源码如下:
private static class IntegerCache {
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++);
}
private IntegerCache() {}
}