多维数组
今日学习总结:
多维数组
针对数组中的元素类型没有特殊要求,所以允许数组的元素是数组。多维数组可以理解为数组的数组
数组中的每个数组元素可以是一个数组,但是不要求每个充当元素的数组长度一致
int[][] arr={{1,2,3,4,5},{3,4},{6,7,8,9}}; 二维数组// System.out.println(arr.length); 获取第一维度的长度值,就是数组类型元素的个数// System.out.println(arr[0].length);获取第二维度的长度值,每个数组元素数组可以等长,也可以变长for(int[] temp:arr) System.out.println(temp);for(int i=0;i<arr.length;i ){ for(int k=0;k<arr[i].length;k ) System.out.printf("arr[%d][%d]=%d\t",i,k,arr[i][k]); System.out.println();}
包装类和Number
一般地当需要使用数字的时通常使用内置数据类型,如byte、int、long、double 等。然而在实际开发过程中,经常会遇到需要使用对象,而不是内置数据类型的情形。为了解决这个问题,Java 语言为每一个内置数据类型提供了对应的包装类。
所有的数值类型数据的包装类Integer、Long、Byte、Double、Float、Short都是抽象类 Number 的子类
byte–>Byte short–>Short int–>Integer long–>Long
float–>Float double–>Double
char–>Character
boolean–>Boolean
int k=100;Integer k=100; 100是简单类型,但是可以直接赋值给复杂类型,装箱操作int k1=k; k是复杂类型,但是可以直接赋值给简单类型,这是拆箱操作
这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类。相似的,编译器也可以把一个对象拆箱为内置类型。Number 类属于 java.lang 包
输入是字串,如果进行数据类型转换String ss="123";int kk=Integer.parseInt(ss);//Integer kk=...Integer k2=Integer.valueOf(ss);//int k2=..如果转换失败则报错,例如ss="123d"可以是具体数据类型转换为字串类型"" 任意类型数据
练习题
int和Integer有什么区别?谈谈Integer的值缓存范围**【注意】**
int是整形数字,是Java的8个原始数据类型(PrimitiveTypes,boolean、byte、short、char、int、float、double、long)之一。Java 语言虽然号称一切都是对象,但原始数据类型是例外
Integer是int对应的包装类,它有一个int类型的字段存储数据,并且提供了基本操作,比如数学运算、int和字符串之间转换等。在Java5中,引入了自动装箱和自动拆箱功能boxing/unboxing,Java可以根据上下文,自动进行转换,极大地简化了相关编程
大部分数据操作都是集中在有限的、较小的数值范围,因而,在Java 5中新增了静态工厂方法valueOf,在调用它的时候会利用一个缓存机制,带来了明显的性能改进。按照Javadoc这个值默认缓存是-128到127之间
注意事项:
基本类型均具有取值范围,在大数*大数的时候,有可能会出现越界的情况
基本类型转换时,使用声明的方式。例:long result= 1234567890 * 24 * 365;结果值一定不会是你所期望的那个值,因为1234567890 * 24已经超过了int的范围,如果修改为:long result=1234567890L * 24 * 365;就正常了
慎用基本类型处理货币存储。如采用double常会带来差距,常采BigDecimal、整型解决该问题
BigDecimal d1=new BigDecimal("1234567890.123456789");如果使用new BigDecimal(1234567890.123456789)则存放数据出错BigDecimal可以提供任意精度的数字,同时提供了对应的计算方法,但是计算速度明显比double类型差
优先使用基本类型。原则上,建议避免无意中的装箱、拆箱行为,尤其是在性能敏感的场合
如果有线程安全的计算需要,建议考虑使用类型AtomicInteger、AtomicLong 这样的线程安全类。部分比较宽的基本数据类型,比如 float、double,甚至不能保证更新操作的原子性,可能出现程序读取到只更新了一半数据位的数值
字符串
字符串实际属于类,实际上所谓的字符串就是指一组字符的有序序列,可以使用双引号进行定义,属于复杂类型
String s1="asdfsafd"; 字符串char c='a' 字符类型
字符串指的是字符的序列,有两种类型的字符串,可以使用3个不同的类进行定义一种是创建以后不需要改变的,称为字符串常量,在Java中,String类用于存储和处理字符串常量
- 另外一种字符串是创建以后,需要对其进行改变的,称为字符串变量,在Java中
- StringBuilder/StringBuffer类用于存储和操作字符串变量
- 字符串有长度限制,在编译期要求字符串常量池中的常量不能超过65535,并且在javac执行过程中控制了最大值为65534。在运行期,长度不能超过Int的范围,否则会抛异常。
String类型字串
字符串在Java中以String类别的一个实例存在
不可变immutable字符串。含义是一个字符串对象一旦被配置,它的内容就是固定不可变的
(immutable),如果需要进行修改则会引发对象的新建。
不要以为下面的操作就是改变一个字符串对象的内容
String str ="Just"; str ="Justin";
Java为了提高字符串的处理效率,提供了一个池子,其中存放一些常用的字串。对于一些可以共享的字符串对象,会先在String池中查找是否存在相同的String内容
String s1="abc"; String s2=new String("abc"); System.out.println(s1==s2);//针对复杂类型==比较的是两个对象的地址值 System.out.println(s1.equals(s2));//比较的是具体内容
String s1 = "abc"; String s2 = "ab" "c"; String s3 = new String("abc"); System.out.println(s1 == s2);//true常量池 System.out.println(s1 == s3);//false System.out.println(s1.equals(s2));//true System.out.println(s1.equals(s3));//true
Integer k1=726; //-128到127时==为真,因为常量池的存在 Integer k2=726; System.out.println(k1==k2); System.out.println(k1.equals(k2));
创建字串对象
new String()空的字符串常量,例如String s=new String(); new String(String value),例如Strings=new String(“abcd”); new String(char value[])例如char[] c=new char[]{‘a’,’b’};String s=newString(c);实际上就是创建一个字符串”ab” new String(StringBuffer buffer)
字串的使用
字符串必须使用“”来包括您的文字,在Java中单双引号具有不同的含义,特别注意字符串的字符是使用Unicode字符来建构
字符串的串接在Java中可以直接使用’ / =’,安装规则不允许重新定义运算符,但是Java重新定义了两个运算符
String msg ="哈啰!";msg = msg "Java程序设计!";System.out.println(msg);
字符串方法
- length()取得字符串的字符长度
String ss="abc中国"; System.out.println(ss.length());//5在Java中所使用的编码字符集为Unicode
注意:数组中的length是属性,调用方法为arr.length。而String中的length是方法,调用方法为string.length()
- equals()判断原字符串中的字符是否相等于指定字符串中的字符。考点在于equals和==的区别
public boolean equalsIgnoreCase(String anotherString);与方法equals的用法相似,只是它比较时不计大小写.实现机制实际上就是将字串转换为全大写或者全小写再进行比较
toLowerCase() 转换字符串中的英文字符为小写
- toUpperCase() 转换字符串中的英文字符为大写
String s1 = "a sdfa123sd,f";StringBuilder sb = new StringBuilder();for (int i = 0; i < s1.length(); i ) { char temp = s1.charAt(i); if (temp >= 'a' && temp <= 'z') { char tt = (char) (temp - 32); sb.append(tt);//在sb的末尾追加字符 }else sb.append(temp);}System.out.println(sb);
- 对已有字串进行反转操作
String s1 = "asdfasdf";StringBuilder sb=new StringBuilder();for(int i=s1.length()-1;i>=0;i--) sb.append(s1.charAt(i));System.out.println(sb);
public int compareTo(String anotherString);如果当前字符串与参数字符串完全相同,则compareTo()方法返回0;如果当前字符串按字母序大于参数字符串,则compareTo()方法返回大于0的整数;反之,则返回小于0的整数
public String concat(String str); 该方法把参数字符串连接到当前字符串的尾部,并返回这个连接而成的字符串,但当前字符串本身不改变
使用 来串接字符串以达到附加新字符或字符串的目的,但 会产生一个新的String实例。不建议使
用 来进行字符串的串接,建议使用StringBuilder或者StringBuffer
将输入的字符串转换为整数、浮点数等
double dd=Double.parseDouble("12.34");/valueOf Integer.parseInt() Short.parseShort Booealn.parseBoolean... 有可能会出现转换失败情形,报错并中断程序的允许[鲁棒性差] "" double
字符串中子串的查找与字符串中单个字符的查找相似
- int indexOf(Stringstr)从左向右开始查找str的起始下标,如果找到了则返回str起始位置的下标,如果查找不到则返回-1
- int indexOf(String str,int fromIndex)从指定下标位置fromInde开始左向右查找str的下标
String ss="System.out.println(s1.compareTo(s2));";int pos=ss.indexOf("outw");System.out.println(pos);
要求输出所有.的下标位置String ss = "System.out.println(s1.compareTo(s2));";int pos = ss.indexOf(".");int k = 0;while (pos > -1) { System.out.println("第" ( k) "次出现的位置为:" pos); pos=ss.indexOf(".",pos 1);}
- int lastIndexOf(String str)从右向左开始查找str的起始下标
- int lastIndexOf(String str, intfromIndex)从指定下标位置fromInde开始右向左查找str的下标
查找最有一个点的出现位置int pos=ss.lastIndexOf(".")
- endsWith(“str”):boolean 判断字串是否以str为结尾
- boolean startsWith(String )判断字串是否以string为开头
- char charAt(int index)获取指定下标index位置上的字符
- char[ ] toCharArray()将字串转换为char数组
-字符串中字符的替换String replace(char oldChar, char newChar)将字串中指定的字符oldChar转换为新的字符newChar,并返回替换后的结果
String s2=ss.replace(".", "111"); 将字符串ss中的字串.转为111统计点出现的次数String ss = "System.out.println(s1.compareTo(s2));";String s2 = ss.replace(".", "");System.out.println((ss.length() - s2.length()) / ".".length());
- String replaceFirst(String regex, String
replacement)用字符串replacement的内容替换当前字符串中遇到的第一个和字符串regex相一致的子串,并将产生的新字符串返回 - String replaceAll(String regex, Stringreplacement)用字符串replacement的内容替换当前字符串中遇到的所有和字符串regex相一致的子串,并将产生的新字符串返回
练习题
获取指定字符串asdkbfasldkbnv,cnvzxnkbjfdfkd中kd的出现次数
String ss = "asdkbfasldkbnv,cnvzxnkbjfdfkd";String s2 = ss.replace("kd", "");System.out.println((ss.length() - s2.length()) / "kd".length());
输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数
使用数组存放出现次数:int[] times=new int[4]; 0-英文1-空格2-数字3其它Scanner sc = new Scanner(System.in);while (true) { System.out.println("请输入一行字符,以回车结束,输入quit则退出程序"); String ss = sc.nextLine(); if("quit".equals(ss)) break; int[] arr = new int[4]; for (int i = 0; i < ss.length(); i ) { char c = ss.charAt(i); if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) arr[0] ; else if (c == ' ') arr[1] ; else if (c >= '0' && c <= '9') arr[2] ; else arr[3] ; } System.out.printf("英文字母出现次数为%d,空格出现次数为%d,数字出现次数为%d,其它字符出现次数为%d", arr[0], arr[1], arr[2], arr[3]);}
判断中文具体的匹配中文及字符方法:/[\u4E00-\u9FA5\uF900-\uFA2D]/
将整数转换为大写的汉字,例如1234转换为壹仟贰佰叁拾肆元
int kk=123456;StringBuilder sb=new StringBuilder();char[] ns=new char[]{'零','壹','贰','叁','肆','伍','陆','柒','捌','玖'};char[] us=new char[]{'圆','拾','佰','仟','萬','拾'};String ss="" kk;for(int i=0;i<ss.length();i ){ char temp=ns[ss.charAt(i)-'0']; sb.append(temp); }int k=0;for(int i=ss.length()-1;i>=0;i--){ sb.insert(i 1,us[k ]); }System.out.println(sb.toString());
substring用于实现截取字串中的部分内容
- substring(int起始下标):String 获取字符串中从起始下标开始到字串末尾的所有字符
- substring(int起始下标,int终止下标):String获取字符串中指定下标之间的内容,含左不含右
String abc="sdf,sad,fsafd,safsd";//先获取逗号出现的次数从而确定字串可以分的段数String ss=abc.replace(",","");int num=abc.length()-ss.length();获取逗号的出现次数String[] arr=new String[ num];初始化存储子字串的数组int begin=0;int index=abc.indexOf(",");查看第一次逗号出现的位置int k=0;while(index>-1){如果查找到逗号 arr[k ]=abc.substring(begin,index);截取部分内容 begin=index 1; index=abc.indexOf(",",begin); }if(begin<abc.length())补偿最后逗号不出现 arr[k]=abc.substring(begin);for(String temp:arr) System.out.println(temp);
split(“正则式”):String[] 可以按照指定的正则式条件分割字串返回分割后生成的数组
String abc="sdf,sad,fsafd,safsd";String[] arr=abc.split(",");按照逗号作为分割符分割字符串for(String temp:arr) System.out.println(temp);
trim():String去除字符串两端的空格,无论多少个空格
StringBuffer 和 StringBuilder 类
String类型的变量进行修改操作时一定会引发对象的新建
- 在java中所有的复杂类型变量中都会有一个方法hashCode():int,这个值是一个和变量存储位置相关的数据
- 对象的创建和销毁是需要时间代价的
使用StringBuffer和StringBuilder类的前提是频繁的修改操作
和String类不同的是,StringBuffer和StringBuilder类的对象能够被多次的修改且不产生新的未使用对象。StringBuilder类在Java 5中被提出,它和StringBuffer间的最大不同在于StringBuilder的方法不是线程安全的(不能同步访问)。由于StringBuilder相较于StringBuffer有速度优势,所以多数情况下建议使用StringBuilder类。然而在应用程序要求线程安全的情况下,则必须使用
StringBuffer类。
构建对象的方法
StringBuilder sb1=new StringBuilder(“初始内容”);
StringBuilder sb2=new StringBuilder(int初始化容积);
StringBuilder或者StringBuffer类支持的主要方法:
不同于String类型,没有 或者 =这样的运算符
StringBuffer append(任意类型数据) 将指定的类型类型数据转换为字符串追加到此字符序列末尾
StringBuffer reverse()将此字符序列用其反转形式取代。
String ss = "1234567890";StringBuilder sb = new StringBuilder(ss);// 将String转换为StringBuildersb.reverse();System.out.println(sb.toString());// 将StringBuilder转换为String如果使用StringBuffer只是替换名称即可,StringBuffer和StringBuilder中的方法基本一致
delete(int start, int end)移除此序列的子字符串中的字符
insert(int offset, 任意类型数据)将任意类型数据参数的字符串表示形式插入此序列中,原始位置上的内容后移
replace(int start, int end, String str)使用给定 String 中的字符替换此序列的子字符串中的字符。
下面的方法和String类的方法类似:
int capacity()返回当前容量。表示可以放多少个字符,实际存放的数量需要通过length进行获取。容积会随着存放数据量的变化而增长
char charAt(int index)返回此序列中指定索引处的 char 值
void ensureCapacity(int minimumCapacity)确保容量至少等于指定的最小值
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)将字符从此序列复制到目标字符
数组 dst
int indexOf(String str)返回第一次出现的指定子字符串在该字符串中的索引
int indexOf(String str, int fromIndex)从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引
int lastIndexOf(String str)返回最右边出现的指定子字符串在此字符串中的索引
int lastIndexOf(String str, int fromIndex)返回 String 对象中子字符串最后出现的位置
int length() 返回长度(字符数)
void setCharAt(int index, char ch)将给定索引处的字符设置为 ch
String substring(int start)返回一个新的 String,它包含此字符序列当前所包含的字符子序列
String substring(int start, int end)返回一个新的 String,它包含此序列当前所包含的字符子序列
String toString()返回此序列中数据的字符串表示形式。
练习题
String str = "零壹贰叁肆伍陆柒捌玖";char[] cc = str.toCharArray();str="圆拾佰仟萬拾佰仟亿拾佰仟兆拾佰仟";double d1 = 34567.89012; String ss = "" d1;StringBuffer sb = new StringBuffer();for (int i = 0; i < ss.length(); i ) { char rr = ss.charAt(i); if ('.' == rr)sb.append("."); else { int pos = rr - '0'; char temp = cc[pos]; sb.append(temp); }} String s1 = sb.substring(0, sb.indexOf("."));StringBuilder res1=new StringBuilder();int count=0;for(int i=s1.length()-1;i>=0;i--){ res1.insert(0,str.charAt(count )); res1.insert(0, s1.charAt(i)); }String s2 = sb.substring(sb.indexOf(".") 1);char c1=s2.charAt(0);res1.append(c1).append("角");c1=s2.charAt(1);res1.append(c1).append("分");System.out.println(res1);
三种字串类型的使用
String是Java中基础且重要的类,并且String也是Immutable类的典型实现,被声明为final class,除了hash这个属性其它属性都声明为final,因为它的不可变性,所以例如拼接字符串时候会产生很多无用的中间对象,如果频繁的进行这样的操作对性能有所影响。
StringBuffer就是为了解决大量拼接字符串时产生很多中间对象问题而提供的一个类,提供append和add方法,可以将字符串添加到已有序列的末尾或指定位置,它的本质是一个线程安全的可修改的字符序列,把所有修改数据的方法都加上了synchronized。但是保证了线程安全是需要性能的代价的。
如果字符串拼接操作不需要线程安全则使用StringBuilder,StringBuilder是JDK1.5发布的,它和StringBuffer本质上没什么区别,就是去掉了保证线程安全的那部分,减少了开销。
StringBuffer 和 StringBuilder 二者都继承了 AbstractStringBuilder ,底层都是利用可修改的char数组(JDK 9 以后是 byte数组)。所以如果我们有大量的字符串拼接,如果能预知大小的话最好在new StringBuffer 或者StringBuilder 的时候设置好capacity,避免多次扩容的开销。扩容要抛弃原有数组,还要进行数组拷贝创建新的数组。
一般开发通常情况下少量的字符串拼接其实没太必要担心,如String str = “aa” “bb” “cc”;像这种没有变量的字符串,编译阶段就直接合成"aabbcc"了,然后看字符串常量池里有没有,有也直接引用,没有就在常量池中生成,返回引用。如果是带变量的,其实影响也不大,JVM会帮我们优化了。
总之:
1、在字符串不经常发生变化的业务场景优先使用String(代码更清晰简洁)。如常量的声明,少量的字符串操作(拼接,删除等)。
2、在单线程情况下,如有大量的字符串操作情况,应该使用StringBuilder来操作字符串。不能使用String" "来拼接而是使用,避免产生大量无用的中间对象,耗费空间且执行效率低下(新建对象、回收对象花费大量时间)。如JSON的封装等。
3、在多线程情况下,如有大量的字符串操作情况,应该使用StringBuffer。如HTTP参数解析和封装等。
Random类
Random类中实现的随机算法是伪随机,也就是有规则的随机。在进行随机时,随机算法的起源数字称为种子数seed,在种子数的基础上进行一定的变换,从而产生需要的随机数字创建对象
new Random()构造方法使用一个和当前系统时间对应的相对时间有关的数字作为种子数,然后使用这个种子数构造Random对象
new Random(long seed)构造方法可以通过制定一个种子数进行创建
Random类中的常用方法
boolean nextBoolean()方法的作用是生成一个随机的boolean值,生成true和false的值几率相等,也就 是都是50%的几率
double nextDouble()方法的作用是生成一个随机的double值,数值介于[0,1.0)之间
int nextInt()该方法的作用是生成一个随机的int值,该值介于int的区间,也就是2e9之间
int nextInt(int n)方法的作用是生成一个随机的int值,该值介于[0,n)的区间,也就是0到n之间的随机int值,包含0而不包含n**
void setSeed(long seed)方法的作用是重新设置Random对象中的种子数。设置完种子数以后的
Random对象和相同种子数使用new关键字创建出的Random对象相同
Random r = new Random();int kk=r.nextInt();System.out.println(kk);
生成随机的字符值Random r = new Random();int kk=r.nextInt(26);System.out.println((char)('a' kk));
摇号器
public static boolean exists(int[] arr,int num){ boolean res=false; for(int i=0;i<arr.length;i ){ if(num==arr[i]){ res=true; break; } } return res; } //超级大乐透,取值1-36,不重复public static void main(String[] args) { int[] res=new int[7]; Random r=new Random(); int i=0; while(i<=6){ int temp=r.nextInt(36) 1; boolean rb=exists(res, temp); if(!rb) res[i ]=temp; } for(int temp:res) System.out.println(temp); } ?输出前需要排序
注意:一般开发中不使用随机种子值,因为系统默认使用的是系统的当前时间作为种子值。
生成长度在1-10个字符以内,内容为[a-zA-Z]的随机长度的随机字符串
public static String generateString() { String source = "abcdefghijkmnpqrstuvwxyzQWERTYUIOPASDFGHJKLZXCVBNM"; Random r = new Random(); int cc = r.nextInt(10) 1; StringBuilder sb=new StringBuilder(); for (int i = 0; i < cc; i ) { int randomIndex=r.nextInt(source.length()); char temp=source.charAt(randomIndex); sb.append(temp); } return sb.toString(); }public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (true) { System.out.println("点q键退出,否则生成下一字符串"); String str = sc.nextLine(); if ("q".equals(str.trim())) break; else System.out.println(generateString()); } }
Math类中的数学函数
java.lang.Math 类包含的方法进行基本的数字操作,如基本的指数,对数,平方根和三角函数等
java.lang.Math类的字段
static double E – 这就是double值,该值是比任何其他更近到e,自然对数的基础
static doublePI – 这就是double值,该值是比任何其他更接近到pi
System.out.println(Math.PI);
java.lang.Math类方法
Math.abs 求绝对值,典型使用场景就是浮点数的等值判定问题
double k=0;for(int i=0;i<10;i ) k =0.1;if(Math.abs(k-1)<1e-6) System.out.println("结果为1");
Math.ceil 得到不小于某数的最小整数
Math.floor 得到不大于某数的最大整数
double dd = 12.5;System.out.println(Math.ceil(dd));System.out.println(Math.floor(dd));dd = -12.5;System.out.println(Math.ceil(dd));System.out.println(Math.floor(dd));
Math.max 求两数中最大
Math.min 求两数中最小
Math.round 四舍五入返回int型或者long型
Math.rint 求距离某数最近的整数(可能比某数大,也可能比它小),返回double
Math.random 返回0,1之间的一个随机数
Random r=new Random();System.out.println(r.nextDouble()); System.out.println(Math.random());
三角函数
Math.sin 正弦函数Math.asin 反正弦函数
Math.cos 余弦函数Math.acos 反余弦函数
Math.tan 正切函数Math.atan 反正切函数
Math.toDegrees 弧度转化为角度 Math.toRadians 角度转化为弧度
指数计算
Math.sqrt求开方 Math.sqrt(4)
Math.pow 求某数的任意次方, 抛出ArithmeticException处理溢出异常
System.out.println(Math.sqrt(3));//1.7320508075688772System.out.println(Math.pow(5, 3.2));//172.4662076826519
Math.exp 求e的任意次方
Math.log10 以10为底的对数
Math.log 自然对数
Date类型
Date now=new Date();取得系统的时间,也可以使System.currentTimeMillis()方法。
Date dd=new Date(); 获取系统当前时,其中包含年月日时分秒System.out.println(dd);
Date中并不是存放具体的年月日等数据,实际上存放的是从从1970年1月1日0时0分0秒开始,到程序执行取得系统时间为止所经过的毫秒数。进行输出时才进行显示格式的转换