数组
数组的优点
数组中每个元素的内存地址在空间存储上是连续的
每个元素类型相同,占用的空间大小一样
知道第一个元素的内存地址,可以通过数学表达式计算,数组检索效率是最高的
数组中存储的数据,在检索的方面,不是一个一个找,而是通过数学表达式算出来的(算出一个内存地址,根据地址拿到值)
数组的缺点
为了保证数组中元素的内存地址连续,在随机删除或者增加元素的时候效率较低(对于最后一个元素增删的效率没有影响)
数组不能存取大数据量,在内存中很难找到很大的连续的内存空间
动态初始化:int[] array=new int[5];
静态初始化:int[] array1={1,3,3,9,0};
Object [] objects ={new Object(),new Object(),new Object()};输出的话是内存地址?
main程序中的数组解释
jvm调用main方法,传过来一个长度为0的数组,这个数组是留给用户的,用户可以在控制台上输入参数,这个参数自动转化为String类型
idea中run下有个edit configurations,下有个program argument,输入的参数就在上面写
public class Array01 {
public static void main(String[] args) {
if(args.length!=2){
System.out.println("请输入用户的账号和密码");
return;
}
//运行到这说明数组是两个
String id =args[0];
String password=args[1];
//这里最好是damin.equals(id),可以避免空指针异常
if(id.equals("admin")&&password.equals("123")){
System.out.println("登陆成功");
}else{
System.out.println("登录失败");
}
}
}
Animal数组中可以存储cat类型的数据,父类类型的数组可以存储子类的对象
数组只能存储对象的内存地址。数组中存储的每个元素是引用
数组扩容数组长度一旦被确定不可变,数组满了需要扩容,先建一个更大的数组,将小容量数组的数据一个一个拷贝过去,效率较低
public class Array02 {
public static void main(String[] args) {
int [] src={1,2,3,4,5};//源数组
int [] dest=new int[20];//动态初始化目标数组
//第一个参数是源数组,要复制的数组。第二个参数是从源数组哪个位置开始复制。第三个参数是复制到哪个数组上
//第四个参数是复制到目标数组从哪个位置开始。第五个参数是复制多长
//System.arraycopy(src,0,dest,3,2);
System.arraycopy(src,0,dest,0,src.length);
for (int i = 0; i <dest.length ; i++) {
System.out.println(dest[i]);
}
}
}
数组模拟栈数据结构
/*
编写程序,使用一维数组,模拟栈数据结构。
要求:
1、这个栈可以存储java中的任何引用类型的数据。
2、在栈中提供push方法模拟压栈。(栈满了,要有提示信息。)
3、在栈中提供pop方法模拟弹栈。(栈空了,也有有提示信息。)
4、编写测试程序,new栈对象,调用push pop方法来模拟压栈弹栈的动作。
*/
public class Shuzumonizhan {
public static void main(String[] args) {
Object[] a=new Object[4];
Stack s=new Stack(a);
s.push("SSS");
s.push(1);
s.push(2);
for (int j = a.length-1; j >= 0; j--) {
System.out.println("栈的数据是: "+a[j]);
}
s.pop();
s.pop();
Cat c=new Cat();
Cat c2=new Cat();
s.push(c);
s.push(c2);
for (int j = a.length-1; j >= 0; j--) {
System.out.println("栈的数据是: "+a[j]);
}
}
}
class Stack{
Object [] objects;
int index=0;
public Stack(Object[] objects) {
this.objects = objects;
}
public void push(Object o){
if(index<objects.length){
objects[index]=o;
index++;
System.out.println(o +" 进栈成功");
System.out.println("index的值是 "+index);
}else {
System.out.println("栈满了 "+o+" 进栈失败");
}
}
public void pop (){
if(index<=0){
System.out.println("栈空了");
}else{
System.out.println(objects[index-1]+" 出栈成功");
objects[index-1]=null;
System.out.println(objects[index-1]);
}
index--;
System.out.println("index的值是 "+index);
}
}
class Cat{
}
实现酒店管理系统的部分功能
public class HotelMgSystem {
public static void main(String[] args) {
Hotel hotel=new Hotel();
hotel.showInfo();
}
}
//酒店对象,酒店中有二维数组,二维数组模拟大厦
class Hotel{
private Room [][] rooms;
public Hotel() {
rooms=new Room[3][10];//3层每层有十个房间
//创建三十个Room对象放进去
for (int i = 0; i <rooms.length ; i++) {
for (int j = 0; j <rooms[i].length ; j++) {
if (i==0){
rooms[i][j]=new Room((i+1)*100+j,"单人间",true);
}else if (i==1){
rooms[i][j]=new Room((i+1)*100+j,"标准间",true);
}else{
rooms[i][j]=new Room((i+1)*100+j,"总统套房",true);
}
}
}
}
public Hotel(Room[][] rooms) {
this.rooms = rooms;
}
//打印酒店所有房间的信息,遍历二维数组
public void showInfo(){
for (int i = 0; i <rooms.length ; i++) {
for (int j = 0; j <rooms[i].length ; j++) {
System.out.print(rooms[i][j]);
}
//换行,因为里面的循环负责输出一层
System.out.println();
}
}
public void dingfang(int roomno){
//假设房间号207
rooms[roomno/100-1][roomno%100-1].setStatus(false);
}
public void tuifang(int roomno){
rooms[roomno/100-1][roomno%100-1].setStatus(true);
}
}
class Room{
private int no;
private String type;//标准间,单人间,豪华间,总统套房
private boolean status;//房间是否空闲,true表示空闲可以被占用
public Room() {
}
public Room(int no, String type, boolean status) {
this.no = no;
this.type = type;
this.status = status;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean getStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
//equals 方法重写
//判断两个对象是否相等,这里就是两个房间是否相等
@Override
public boolean equals(Object obj) {
if(obj== null&&!(obj instanceof Room))return false;
if (this==obj) return true;
Room room = (Room) obj;
return this.no==room.getNo();
}
//toString方法重写
@Override
public String toString() {
//return "房间号: "+no+"房间类型: "+type+"是否空闲: "+status;
return "[" +no+" , "+type+" , "+(status?"空闲":"占用") + "]";//三元运算符
}
}
现在存在数组中,就是存在内存中,一断电什么都没,后续存到数据库中,数据库会把数据存到硬盘文件中
Arrayas工具类
其中有一个sort方法是静态的,类名点方法名直接调
冒泡,选择排序算法
二分法查找算法
import java.util.Arrays;
public class Array {
public static void main(String[] args) {
int [] a ={1,2,3,6,32,222,3333};
Arrays.sort(a);
for (int i = 0; i <a.length ;i++) {
System.out.println(a[i]);
}
//二分法查找(建立在排序的基础上)
//判断该数组是否有这个元素
int index=Arrays.binarySearch(a,32);
System.out.println(index==-1?"该元素不存在":"下标为 "+index);
}
}
常用类
String
StringBuffer
基础类型对应的8个包装类
日期相关类
数字相关类
Random
Enum
String
String是引用类型
这里说字符串常量池存放在方法区中,如果不是new对象,引号括起来的内容存在字符串常量池中,如果是new对象会在堆中开辟空间,如下图
String s1 =“xxx”
String s2 =“xxx”
双等号比较的是内存地址,所以如果是直接赋值的,那么用双等号判断s1s2是否相等比较的是内存地址,以上结果是相等的,如果new对象出来比较返回的是false
所以要用equals方法比较对象是否相同,String类重写了equals方法,toString方法
public class Tese {
public static void main(String[] args) {
/*
一共创建几个对象,3个
字符串常量池一个,堆内存中两个String对象
*/
String s1=new String("aaa");
String s2=new String("aaa");
}
}
垃圾回收器不会释放常量的
String类的构造方法
char数组要用单引号
public class Tese {
public static void main(String[] args) {
char [] c={'中','国','人'};
String s=new String(c);
System.out.println(s);//转换成字符串,中国人
}
}
public class Tese {
public static void main(String[] args) {
char [] c={'中','国','人'};
String s=new String(c,1,1);//从第下标为1的开始,长度是1截取出来
System.out.println(s);//输出是国
}
}
System.out.println("sssssssssa".contains("sss"));
//判断前面的字符串包不包含后面的字符串
System.out.println("wwwwwwwaaaa".startsWith("w"));
//判断是否以后面字符串开头的
System.out.println("tt.txt".endsWith(".txt"));
//判断是否以后面字符串结尾的
System.out.println("acs".equalsIgnoreCase("Acs"));
//比较字符串是否相等忽略大小写
public class Tese {
public static void main(String[] args) {
byte []bytes ="sadasda".getBytes();
for (int i = 0; i <bytes.length ; i++) {
System.out.println(bytes[i]);
}
}
}//输出是115,97,100,97......
//将字符串转化成字节数组
public class Tese {
public static void main(String[] args) {
byte []bytes ="中国".getBytes();
for (int i = 0; i <bytes.length ; i++) {
System.out.println(bytes[i]);
}
}
}//输出是-28 -72 -83 -27 -101 -67,一个汉字3个字节
//判断某个字符串在当前字符串第一次出现的索引(下标)
System.out.println("phpjavapythoncppc".indexOf("java"));
System.out.println("".isEmpty());
//判断某个字符串是否为空串,其实底层是字符串的length方法
判断数组长度和判断字符串长度不一样
判断数组长度是数组的length属性,判断字符串长度是length方法
System.out.println("phpjavapythoncppc".lastIndexOf("java"));
//判断某个字符串在当前字符串中最后一次出现的索引
String newString="www.baidu.com".replace("baidu","hao123");
System.out.println(newString);
//替换
public class Tese {
public static void main(String[] args) {
String newString="www-baidu-com";
String [] strings=newString.split("-");
for (int i = 0; i <strings.length ; i++) {
System.out.println(strings[i]);
}
}
}//拆分后返回的是个数组,这有个问题,为什么不能用.拆分
System.out.println("www.baidu.com".substring(2));
//从下标为2的位置截取,包括2位置上的字符
System.out.println("www.baidu.com".substring(2,7));
//从2截取到7,不包括7
public class Tese {
public static void main(String[] args) {
char [] chars ="我是中国人".toCharArray();
for (int i = 0; i <chars.length ; i++) {
System.out.println(chars[i]);
}
}
}//将字符串转化成char数组
System.out.println("AAAAAAAA".toLowerCase());//转化成小写
System.out.println("aaaaaaaaaaaa".toUpperCase());//转化成大写
System.out.println(" hello world ".trim());//去除前后空白
Sring中唯一的静态方法valueOf,将非字符串转化成字符串
public class Tese {
public static void main(String[] args) {
String s= String.valueOf(true);
System.out.println(s);
}
}
当参数为引用时,会自动调用该对象的toString方法,现在没重写所以输出的是内存地址
public class Tese {
public static void main(String[] args) {
String s= String.valueOf(new A());
System.out.println(s);
}
}
class A{
}
为什么输出一个引用的时候会自动调用toString方法?
会先调用valuOf方法,valuOf方法会调用toString方法
StringBuffer
如果需要进行频繁的字符串拼接,会有什么问题?
因为java中字符串是不可变的,每一次拼接会产生新的字符串,占用大量的内存
public class StringBuffer1 {
public static void main(String[] args) {
String s="";
for (int i = 0; i <100 ; i++) {
s+=i;
System.out.println(s);
}
}
}//这样在字符串常量池中会有0,01,012,n个对象(字符串)
建议使用StringBuffer或者StringBuilder
StringBuffer底层其实是一个byte[]数组,初始化容量为16(字符串缓冲区对象)
如何优化StringBuffer?
在创建的时候尽可能给定一个初始化容量,减少底层数组的扩容次数。预估一下给个大一些的初始化容量
public class StringBuffer1 {
public static void main(String[] args) {
StringBuffer stringBuffer =new StringBuffer();
stringBuffer.append("A");
stringBuffer.append(123);
stringBuffer.append(true);
stringBuffer.append("中国");
System.out.println(stringBuffer);
}
}
//A123true中国
public class StringBuffer1 {
public static void main(String[] args) {
StringBuffer stringBuffer =new StringBuffer();
String s="";
for (int i = 0; i <100 ; i++) {
//s+="";
stringBuffer.append(i);
System.out.println(stringBuffer);
}
}
}
StringBuffer和StringBuilder区别
StringBuffer中有关键字synchronized修饰,表示在多线程环境下运行是安全的。
基础类型对应的8个包装类
为什么提供8种包装类?
当一个方法参数列表是object o时,可以往里面传一个数字类型1,自动转化成数字类型对应的包装类
8种包装类6个都是对应的数字型的,父类是number,number中的方法都是拆箱的
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
System.out.println(Double.MAX_VALUE);
System.out.println(Double.MIN_VALUE);
通过包装类获取常量的最大值最小值
JDK1.5之后可以自动装箱自动拆箱了
自动装箱,基本数据类型自动转化成包装类
自动拆箱,包装类自动转化成基本数据类型
public class Tese {
public static void main(String[] args) {
Integer i= 100;//自动装箱
int x = i;//自动拆箱
// i是包装类,+要求两边是基本数据类型的数字,自动拆箱了,只有加减乘除等运算的时候
//z中存了一个对象的内存地址 等同于Integer z=new Integer(100);
Integer z= 100;
System.out.println(z+1);
}
}
public class Tese {
public static void main(String[] args) {
Integer a =128;
Integer b =128;
System.out.println(a==b);//返回false
Integer x=127;
Integer y=127;
System.out.println(x==y);//返回true
}
}
java中为了提高效率将[-128到127]之间的所有包装对象提前创建好放到了方法区的”整数型常量池“了,目的是只要使用这个区间的数就不用New了,直接从常量池中取出,所以上面x,y保存的内存地址都指向了常量池中的127,所以上面第二个返回来的是true
池,cache缓存机制,提前备好,优点是效率高缺点是占用内存
Integer类的常用方法
int x = Integer.parseInt("111111111");//如果里面出现中文,会有数字格式化异常
//将字符串转化成数字,静态方法,在输入框中输的是字符串110,保存到数据库要求是数字型的,所以要用这个方法
String int Integer互相转换
public class Tese {
public static void main(String[] args) {
//String-->int
String s1="100";
int i1=Integer.parseInt(s1);
System.out.println(i1+1);
//int-->String
String s2=i1+"";//第一种方法,"101"字符串
System.out.println(s2+1);//字符串拼接,"1001"
//int-->Integer
Integer x=100; //自动装箱
//Integer-->int
int y= x; //自动拆箱
//String-->Integer
Integer k=Integer.valueOf("123");
//Integer-->String
String e =String.valueOf(k);
}
}
日期相关类
怎么获取系统当前时间
怎么格式化时间
String类型的时间转化成Date类型的时间
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTest {
public static void main(String[] args) throws Exception {
//获取当前时间,如果括号填参数,是毫秒
Date nowTime=new Date();//不在lang包下,要导包
System.out.println(nowTime);
//日期格式化的类,按照指定的格式转化,java.tex包下的,专门负责日期格式化
/*
yyyy年,MM月,dd日,HH时,mm分,ss秒,SSS毫秒(1000毫秒=1秒)
除了y M d H m s S 不能随便写,其他都可
*/
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS毫秒");
String s=sdf.format(nowTime);
System.out.println(s);
//有个字符串日期格式,怎么转化成Date类型
String time ="2008-08-12 08:02:12 222";
// SimpleDateFormat sdf1=new SimpleDateFormat("格式不能随便写,要和上面的字符串格式相同");
SimpleDateFormat sdf1=new SimpleDateFormat("yyy-MM-dd HH:mm:ss SSS");
Date dateTime =sdf1.parse(time);
System.out.println(dateTime);
}
}
//Fri Aug 07 16:16:32 CST 2020
//2020-08-07 16:16:32 371毫秒
//Tue Aug 12 08:02:12 CST 2008
获取1970年1月1日,0点0分0秒 0000到当前系统时间的总毫秒数
public class DateTest {
public static void main(String[] args) {
//获取1970年1月1日,0点0分0秒 0000到当前系统时间的总毫秒数,每一秒增加1000
long nowTimeMillis =System.currentTimeMillis();
System.out.println(nowTimeMillis);
//统计一个方法耗时多久
//在开始记录一个毫秒数
long begin=System.currentTimeMillis();
print();
//在方法执行结束记录一个毫秒数
long end =System.currentTimeMillis();
System.out.println("方法耗时 "+(end-begin)+"毫秒");
}
public static void print(){
for (int i = 0; i <1000 ; i++) {
System.out.println("i= "+i);
}
}
}
简单总结System类(lang包下)的方法和相关属性
System.out(out是System的静态变量)
System.out.println();(println()方法不是System类的,是PrintStream类的)
System.gc()(建议启动垃圾回收器)
System.currentTimeMillis()(获取1970年1月1日,0点0分0秒 0000到当前系统时间的总毫秒数)
System.exit(0)(退出jvm)
Date time2=new Date(System.currentTimeMillis()-1000*60*60*24);
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS毫秒");
System.out.println( sdf.format(time2));
//到昨天这个时候的时间
//输出是2020-08-06 16:41:49 928毫秒
//因为是北京时间所以有8个小时的时差,东八区
数字相关类
import java.text.DecimalFormat;
public class Number {
public static void main(String[] args) {
//DecimalFormat df =new DecimalFormat("数字格式");
/*
#代表任意数字,,代表千分位,.代表小数点 0代表不够补0
###,###.##
*/
DecimalFormat df =new DecimalFormat("###,###,###.##");
System.out.println(df.format(12222222.22));
}
}
java.math.BigDecimal
BigDecimal属于大数据,精度极高(比double高),不是基本数据类型,属于java对象,引用数据类型,这是sun提供的一个类,专门用在财务软件中
import java.math.BigDecimal;
public class Number {
public static void main(String[] args) {
BigDecimal v=new BigDecimal(100);
BigDecimal v1=new BigDecimal(1020);//不是普通的1020,是精度极高的
//求和不能直接相加,要调方法
BigDecimal v3=v.add(v1);
System.out.println(v3);
System.out.println(v1.divide(v));
}
}
Random类
import java.util.Random;
public class Random1 {
public static void main(String[] args) {
Random random=new Random();
int i= random.nextInt();//随机产生int范围内的随机数
System.out.println(i);
//下一个int是101,不包括101,就是小于101
int i1=random.nextInt(101);
System.out.println(i1);
}
}
随机生成5个随机数放在一个数组里,如果重复重新生成
import java.util.Random;
public class RandomHomeWork {
public static void main(String[] args) {
int [] a= new int[5];
//初始化数组里的值为-1
for (int i = 0; i <a.length ; i++) {
a[i]=-1;
}
Random random=new Random();//随机数在0-100闭区间内
int index=0;
while (index<a.length) {
int num=random.nextInt(10);
System.out.println("随机数是: "+num);
if(!contains(a,num )){
a[index]=num;
index++;
}
}
System.out.println("=========================");
for (int i = 0; i <a.length ; i++) {
System.out.println(a[i]);
}
}
public static boolean contains(int [] a,int b){
for (int i = 0; i <a.length ; i++) {
if (a[i]==b){
return true;
}
}
return false;
}
}
枚举Enum
有可能遇到一个方法执行结果有两证情况,可以将返回类型设计成布尔类型,但如果是三种情况,四种情况,或者五种情况就要枚举出来了,就要用到枚举类型
public class enum1 {
public static void main(String[] args) {
Result r=divide(10,2);
System.out.println(r==Result.SUCCESS?"计算成功":"计算失败");
}
public static Result divide (int a,int b){//返回值是Result类
try {
int c=a/b;
return Result.SUCCESS;
}catch (Exception e){
return Result.FAIL;
}
}
}
/*
枚举:一枚一枚列举出来
枚举编译之后也是生成class文件
是一种引用类型
枚举中的每一个值可以看作是一个常量
*/
enum Result{
//SUCCESS,FAIL是枚举Result类型的两个值,可以看作“常量”
SUCCESS,FAIL
}