Javaweb微专业第六讲-----数组与字符串
来源:互联网 发布:英文原著推荐 知乎 编辑:程序博客网 时间:2024/04/28 02:24
有时候我们需要一组相同数据类型的变量,这时候我们就要用数组来实现
数 组:用于存储同一类型数据的一个容器。好处:可以对该容器中的数据进行编号,从0开始。数组用于封装数据,就是一个具体的实体。
一、数组的相关操作
1.数组声明、初始化、属性
1.1数组声明的几种方式
type[] 变量名 = new type[数组中元素的个数];
type 变量名[] = new type[数组中元素的个数];
type[] 变量名 = new type[]{逗号分隔的初始化值};
type[] 变量名 = {元素1,元素2…};
2.数组的几种初始化方式
方式一
String[] strs = new String[2];strs[0] = "0";strs[1] = "1";
方式二
String[] strs = new String[]{"0", "1"};
方式三
String[] strs = {"0", "1"};
3.属性
获取数组长度:数组名.length
2.数组的几种遍历方法
2.1 for循环遍历(其他循环遍历也可以)
int[] a = new int[10] ; for(int i=0;i<a.length;i++){ a[i]=0; }
2.2 for-each循环
for(int t:a){ System.out.println(t); }
注:这里t就是数组元素的拷贝,不能通过t来修改数组元素的值
3.数组的排序、查找
3.1 数组的排序
3.1.1 冒泡排序
public void bubbleSort(int a[]) { for (int i = 0; i < a.length - 1; i++){ for (int j = 0; j < a.length - 1; j++){ if (a[j] > a[j + 1]) { int temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } }
3.1.2 选择排序
public void selectSort(int a[]) { for (int n = a.length; n > 1; n--) { int i = max(a,n); int temp = a[i]; a[i] = a[n - 1]; a[n - 1] = temp; } }
3.1.3 插入排序
public void insertSort(int a[]) { for (int i = 1; i < a.length; i++) { int t = a[i]; int j; for (j = i - 1; j >= 0 && t < a[j]; j--) { a[j + 1] = a[j]; } a[j + 1] = t; } }
3.1.4 Arrays.sort()方法:
import java.util.Arrays; //导入包public class Main { public static void main(String[] args) { int a[] = new int[10]; Arrays.sort(a); }}
3.2 数组的查找
3.2.1 二分查找法
public static int binarySearch(int[] arr,int key){ int min,max,mid; min = 0; max = arr.length-1; mid = (max+min)>>1; //(max+min)/2; while(arr[mid]!=key){ if(key>arr[mid]){ min = mid + 1; } else if(key<arr[mid]) max = mid - 1; if(max<min) return -1; mid = (max+min)>>1; } return mid; }
3.2.2 用Arrays类进行二分查找
public static int binarySearch(Object[] a, Object key);
例如
Arrays.binarySearch(a, 10);
4.Arrays 类
java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。
给数组赋值:public static void fill(int[] a, int val)。
对数组排序:public static void sort(Object[] a),按升序。
比较两个数组是否相等:public static boolean equals(long[] a, long[] a2)
二分查找数组元素:public static int binarySearch(Object[] a, Object key)
数组拷贝:Arrays.copyOf(original, newLength)
original – 这是要被复制的数组。
newLength – 这是要返回的副本长度。
System.arraycopy(src, srcPos, dest, destPos, length);
通过查看Arrays的源码可以发现实际上:Arrays.copyOf(original, newLength)内部是调用的System.arraycopy(src, srcPos, dest, destPos, length);
5.二维数组
5.1声明与初始化
int[][] arr = new int[2][3];int[][] arr = new int[2][];int[][] arr = {{1,2,3},{4,5},{6,7,8,9}};
5.2 二维数组的遍历
1.for循环遍历二维数组
public class Test { public static void main(String[] args) { int[][] arr = {{1,2,3},{4,5},{6,7,8,9}}; for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr[i].length; j++) { System.out.println(arr[i][j]); } } }}
2.两层for-each循环
public class Test { public static void main(String[] args) { int[][] arr = {{1,2,3},{4,5},{6,7,8,9}}; for (int[] is : arr) { for (int i : is) { System.out.println(i); } } }}
5.3二维数组 的几个问题
1.二维数组的定义格式
int[][] arr = new int[2][]; 可以。
int[][] arr = new int[][3]; 不可以。一定要先给行,在考虑列。
2.int[] x,y[];请问x和y有区别吗?
有区别,x是一维数组,y是二维数组。
二、字符串的相关操作
1.字符串创建
String str=”“;
string str=new String();
注:
a.实际运用中,我们要避免第二种方式,第二种方式创建了两个String对象。首先,通过双引号创建了String对象“abc”。然后,java虚拟机创建一个新的String对象,并把字符串“abc”传入构造函数。这是一次完全没有必要的构造,既影响了性能,也提高了代码阅读难度。
b.这两个对象创建的时期不同,一个是编译时,一个是运行时.
c.String str=”hello”;JVM先根据内容查找对象,如果没找到,则heap上面创建新对象,并将其赋予s1,否则使用已经存在的对象
d.string str=new String(“hello”); jvm直接在heap上创建新的对象,所以在heap中会出现内容相同而地址不同的String对象.
2.字符串的拼接
str=”hello”+”world”
aa.concat(str)
3.字符串的属性与方法
3.1.获取字符串长度
a.length();
3.2 特殊字符
回车 ‘\r’
换行 ‘\n’
Tab ‘\t’
换页 ‘\f’
退格 ‘\b’
单引号 ‘\’
换码符 ‘\’
双引号 ‘\”’
4.String类
4.1 不可修改性
通过String类的源码的我们,value[]属性是final的。这代表一个String对象是不可改变的,String类的方法中我们也找不到任何能够改变字符串的值和长度的方法。这就是字符串的不可改变性
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[];
4.2不能被继承
因为final是最终意思,final限定的类是最终类,没有其子类。所以不能够被继承。关于继承这个概念会在第八讲面向对象详细说明。
4.3 String对象的方法
String类的equals()方法用来确定两个字符串是否相等
charAt()用以得到指定位置的字符
getChars()用以得到字符串的一部分字符串
subString()是提取字符串的另一种方法,它可以指定从何处开始提取字符串以及何处结束
replace()方法可以将字符串中的一个字符替换为另一个字符
toUpperCase()和toLowerCase()方法分别实现字符串大小写的转换
trim()方法可以将字符串中开头和结尾处的空格去掉.
String类提供静态方法valueOf(),它可以将任何类型的数据对象转换为一个字符串。
我们说String类是不可变字符序列,如果频繁的修改,将会产生很多的String对象,开销很大。有时候我们需要用到可变字符序列,jdk为我们提供了StringBuffer类与StringBuilder类。
4.4 String对象的intern()方法
5.StringBuffer类
StringBuffer对象的每次修改都会改变对象自身,这点是和String类最大的区别。StringBuffer是线程安全的(后续笔记中,将讲到多线程编程)。
5.1 StringBuffer创建
StringBuffer sb = new StringBuffer();
StringBuffer sb = new StringBuffer(“xiaoqingchun”);
5.2 StringBuffer的常用方法
StringBuffer reverse();
int lastIndexOf(String str, int fromIndex);
int lastIndexOf(String str);
int indexOf(String str, int fromIndex);
int indexOf(String str);
StringBuffer insert(int offset, double d);
String substring(int start, int end);
CharSequence subSequence(int start, int end);
StringBuffer replace(int start, int end, String str);
StringBuffer deleteCharAt(int index);
StringBuffer delete(int start, int end)
append();
注:不能通过String常量来赋值,String不存与StringBuffer在继承关系,无法进行强转
6.StringBuilder类
6.1 创建
StringBuilder sb= new StringBuilder(“xiaoqingchun!”);
6.2 常用方法
7.String,StringBuffer与StringBuilder的区别
7.1 效率比较
通常情况下 : 三者在执行速度方面的比较:StringBuilder > StringBuffer > String
但是一定是这样的嘛,接下来我们来看4个栗子
栗子1 :
(1)String str = “This is only a” + “simple”+ ” test”;
(2)StringBuffer buffer= new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
这里(1)的效率比(2)的效率高,这是因为jvm在编译的时候,已经直接进行了表达式合并优化,只开辟了一段内存。而编译StringBuffer还要进行append处理,花的时间要长一些
栗子2 :
(1) String str = “This is only a”;
str += “simple”;
str += “test”;
(2)StringBuffer buffer= new StringBuffer (“This is only a”).append(“ simple”).append(“ test”);
(1)的效率优于(2)的效率,因为String是不可变对象,,每次”+=”都会创造新的String对象
栗子3 :
(1)StringBuffer buffer= new StringBuffer ();
for(int i=0;i<50000;i++){
buffer.append(“hello”);
}
(2)StringBuffer buffer= new StringBuffer (250000);
for(int i=0;i<50000;i++){
buffer.append(“hello”);
}
第一周效率比第二种好,因为StringBuffer内部实现是char数组,默认初始化长度为16,每次字符串长度大于char数组长度的时候,JVM会构造新数组,并将原先的数组内容复制到新数组.方法二避免了复制数组的开销。
栗子4 :
(1)private static void test2(String s1,String s2) {
return s1+s2;
}
(2)private static void test2(String s1,String s2) {
return new StringBuffer().append(s1).append(s2);
}
1与2的效率相同,因为JVM会开辟一个内存段,再合并(扩展)内存,所以两者执行的过程是一致的
上述案例可以用一下测试来进行测定
public class Test { public static void main(String[] args) { test1(); test2(); } private static void test1() { Runtime run = Runtime.getRuntime(); long startTime, endTime; long startMem, endMem; System.out.println("方法1"); run.gc();//回收一下垃圾 // 记录开始时的内存及时间信息,并打印到屏幕上 startTime = System.currentTimeMillis(); startMem = run.totalMemory() - run.freeMemory(); System.out.println("开始时候使用的: " + startMem); for (int i = 0; i < 10000; i++) { // 执行需要测试的代码段 String str = "This is only a" + "simple"+ " test"; } // 计算花费的内存及时间,然后打印到屏幕上 endTime = System.currentTimeMillis(); endMem = run.totalMemory() - run.freeMemory(); System.out.println("运行时间:" + (endTime - startTime)); System.out.println("结束时所用内存: " + endMem + ", 增加使用的内存:" + (endMem - startMem)); } private static void test2() { Runtime run = Runtime.getRuntime(); long startTime, endTime; long startMem, endMem; System.out.println("方法1"); //回收一下垃圾 run.gc(); // 记录开始时的内存及时间信息,并打印到屏幕上 startTime = System.currentTimeMillis(); startMem = run.totalMemory() - run.freeMemory(); System.out.println("开始时候使用的: " + startMem); //微小放大法 for (int i = 0; i < 10000; i++) { // 执行需要测试的代码段 StringBuffer sb = new StringBuffer("This is only a").append("simple").append(" test"); } // 计算花费的内存及时间,然后打印到屏幕上 endTime = System.currentTimeMillis(); endMem = run.totalMemory() - run.freeMemory(); System.out.println("运行时间:" + (endTime - startTime)); System.out.println("结束时所用内存: " + endMem + ", 增加使用的内存:" + (endMem - startMem)); }}
7.2 StringBuilder与 StringBuffer的比较
1.StringBuffer线程安全、效率相对低
2.StringBuilder线程不安全、效率相对高
7.3StringBuffer面试关键点:
(1)简单地认为.append()效率好于”+”是错误的。
(2)不要使用new创建String
(3)注意.intern()的使用
(4)在编译期能够确定字符串值的情况下,使用”+”效率最高
(5)避免使用”+=”来构造字符串
(6)在声明StringBuffer对象的时候,指定合适的capacity,不要使用默认值16
(7)注意下面两个的区别,后者开辟了两个内存段
1. String s=”a”+”b”;
2. String s= “a”;
s +=”b”;
7.4 一些面试题
1.请看下面的写法有没有区别? 假设s是一个字符串。
第一种写法:
if(s.equals("world")) { }
第二种写法:
if("world".equals(s)) { }
答案:有却别.如果s是外界传递的一个参数,可能别人传递一个null。这个时候,前者就会有空指针异常。后者没有问题。
推荐:在判断的时候把常量写在前面。
- Javaweb微专业第六讲-----数组与字符串
- Javaweb微专业第十一讲-----继承与抽象类
- Javaweb微专业第十讲-----枚举类
- Javaweb微专业第十二讲-----内部类
- Javaweb微专业第五讲-----从运算符开始讲
- Javaweb微专业第八讲-----面向对象程序设计
- Javaweb微专业第十四讲-----异常处理(预告)
- Javaweb微专业第十四讲-----I/O流
- OC第六讲字符串函数
- Javaweb微专业第九篇-----类与对象
- 第六讲OSGEARH与日月星辰
- 第六章:数组和字符串
- MIT《计算机科学与编程导论》第六讲
- 第六讲 复合控件与CComBSTR
- 第六讲
- 第六讲
- 交作业 php100 第六讲 遍历所有数组
- 我学Delphi心得及笔记----字符串操作(第六讲)
- Android_Service组件详解
- 赛码网常见接受参数的方法
- 数位板的主要参数解析
- Linux下 /proc文件夹内容解析(/proc文件系统解析)
- 使用diskpart
- Javaweb微专业第六讲-----数组与字符串
- kendo grid 的小例子
- JQuery如何获取ID含有特殊字符的DOM元素
- handsontable如何重写右键菜单(contextmenu)
- oracle中两个时间戳相减得到间隔毫秒数
- 删除redis集群上的key的shell脚本
- dp分类大全
- 洛谷3390 矩阵快速幂
- 设计模式(一)之创建型模式