Java 基础小结

1 数组

一维数组

  • 三种初始化方法
int[] a = new int[2];
a[0] = 1;
a[1] = 2;

int[] b = new int[]{5, 1};

int[] c = {8, 9};

数组长度

int[] a = new int[15];
//值为int型常量
a.length = 15;
  • 如果只是对数组进行声明,没有进行创建,则该数组为null,调用length函数会出现空指针异常。
int a[];
// 空指针异常
System.out.println(a.length);
  • 如果对数组进行声明并创建空数组,则数组不为null,length函数正常运行,返回结果为0
int a[] = new int[0];
// 返回结果为0
System.out.println(a.length);

数组判空

  • if (nums == null || nums.length <= 0)

Arrays类方法

Arrays.toString

将数组转换成String类型输出的(否则输出的是数组的地址)

Arrays.sort
  • 对一个数组的所有元素进行从小到大的排序
    Arrays.sort(int[] arr)

  • 对数组a的下标从fromIndex到toIndex-1的元素排序,注意:下标为toIndex的元素不参与排序。
    Arrays.sort(int[] arr, int fromIndex, int toIndex)

  • 对一个数组的所有元素进行从大到小的排序
    Arrays.sort(int[] arr, (a, b) -> b - a);

// 泛型不能使用基本类型(int,double,char),而要使用它们对应的类
Integer[] arr = {1, 4, 2};
Arrays.sort(arr, (a,b) -> b - a);
// [4, 2, 1]
System.out.println(Arrays.toString(arr));
Arrays.asList()
  • 将数组转化成list集合的方法
    List<String> list = Arrays.asList("a", "b", "c");

note:

  1. 该方法适用于对象型数据的数组(Integer、String …),不建议使用于基本数据(int、byte …)
    2)不支持add()、remove()、clear()等方法

二维数组

  • 类似一维数组三种初始化方法
int[][] ar1 = {{1, 2}, {3, 4}};

int[][] ar2 = new int[][] {{1, 2}, {3, 4}};

int[][] ar3 = new int[2][3]
ar3[0] = new int[] {0, 1, 2}
ar3[1][0] = 3;
ar3[1][1] = 4;
ar3[1][2] = 5;

2 字符串

字符串赋值初始化

//空的对象不能做任何操作,相当于string a = null;
string a;

//引用字符串常量
String str = "时间";

//利用构造方法直接实例化
Stringn b = new String("ying")
String c = new String(a);

字符串长度

  • 字符串用length(),数组用length
  • length()方法返回的字符串长度包括字符串中的空格。
  • null字符串不能使用length()
String pass = "123";
int size = pass.length();

字符串判空

1)if (s == null || s.equals(""))
方法直观方便,但是效率比较低
2)if (s == null || s.length() <= 0)
比较字符串长度,效率高
3)if (s == null || s.isEmpty())
Java SE 6.0才开始提供的方法,效率和方法二几乎相等,推荐使用

  • List判空
    if (lcList == null || lcList.size() == 0)

拼接字符串

//"+"运算符
String a = "12" + "34";

//API,在末尾位置拼接字符串
String str = "ab";
str = str.concat("cd");

数字转为字符串

//显示转换,任意数字类型或布尔型
String strInt = String.valueOf(12);
String strLong = String.valueOf(12L);
String strDouble = String.valueOf(12.34);
String strFloat = String.valueOf(3.14f);
String strBool = String.valueOf(false);

//隐式转换,“” +
String str1 = "" + 12;
String str2 = "12" + 34;

获取指定位置的字符

//获取第一个字符,ch = p
String name = "Peter";
char ch = name.charAt(0);

//获取第一次出现的索引,index = 1
String str = "We are";
int index = str.indexOf("e");

//从指定位置往后查索引,index = 5
String str = "We are";
int index = str.indexOf("e", 3);

//获取倒数第一次出现的索引,index = 7
String str = "Let it go!";
int lastIndex = str.lastIndexOf("g");

判断内容

//判断字符串结尾内容
String fileName = "Hello.java";
Boolean bool1 = fileName.endsWith(".java");

//判断字符串句首内容
String str = "小明..."
Boolean bool2 = str.startsWith("小明");

//判断子字符串是否存在
String str = "8D8";
Boolean bool1 = str.contains("D");

//比较字符串是否相等,"=="判断的是内存地址,"equals"判断的是存储的值
String name1 = new String("tom");
String name2 = new String("tom");
boolean bool = name1.equals(name2)
//"equalsIgnoreCase"忽略大小写
String str1 = new String("abc");
String str2 = new String("ABC");
boolean bool = str1.equalsIgnoreCase(str2)

将字符串变成字符数组

String str = "字符串";
char[] ch = str.toCharArray(); 

截取字符串

  • 指定开始的位置、结束位置(可省略):索引
// 23,从起始位置开始到结束位置前
String id = "123456";
String substr = id.substring(1,3);
System.out.println(substr); 

字符串替换

  • replace():旧字符序列换成新字符序列
  • replaceAll():将旧字符串或正则表达式内容,替换成新字符串
  • replaceFirst():替换一次
    • 正则表达式是含有一些具有特殊意义字符的字符串,这些特殊字符称为正则表达式的元字符。例如,“\d”表示数字0~9中的任何一个,“\d”就是元字符;“\.”表示“.”;“\s”表示空格。
    • 转义字符:\n表示换行
// yi文yi个
String str = "一文一个";
String restr = str.replace("一","yi");
System.out.println(restr); 

// ???abc
String str = "123abc";
String restr = str.replaceAll("\\d","?");
System.out.println(restr); 
// [abc]	去除空白内容
String str = " a  bc";
String restr = str.replaceAll("\\s","");
System.out.println("["+restr+"]"); 

// JAva
String str = "Java";
String restr = str.replaceFirst("a","A");
System.out.println(restr); 

字符串分割

  • split:将字符串按照指定的符号分割成数组
// ab	cd	ef
String str = "ab,cd,ef";
String strarray[] = str.spilt(",");
for (int i=0; i<strarray.length; i++){
	System.out.println(strarray[i]); 
}

// [192][168][0][1]		[192][168.0.1]
// 通过参数限定分割的次数
String str = "192.168.0.1";
String strarray1[] = str.split("\\.");
String strarray2[] = str.split("\\.", 2);
for (int i = 0; i < strarray1.length; i++) {
	System.out.print("[" + strarray1[i] + "]");
}
System.out.println();
for (int i = 0; i < strarray2.length; i++) {
	System.out.print("[" + strarray2[i] + "]");
}

字符串大小写转换

  • 将字符串变成大写:toUpperCase()
  • 将字符串变成小写:toLowerCase()
// ABCD		abcd
String str = "abCD";
String str1 = str.toUpperCase();
String str2 = str.toLowerCase();
System.out.println(str1); 
System.out.println(str2); 

格式化字符串

  • 时间格式化
// Thu Jul 15 18:55:22 CST 2021
Date date = new Date();
System.out.println(date);

// 2021 七月 15
String year = String.format("%tY", date);
String month = String.format("%tB", date);
String day = String.format("%td", date);
System.out.println(year+" "+month+" "+day);

// 19 01 17
String hour = String.format("%tH", date);
String minute = String.format("%tM", date);
String second = String.format("%tS", date);
System.out.println(hour+" "+minute+" "+second);

// tF格式:2021-07-15
String str1 = String.format("%tF", date);
System.out.println("tF格式: "+str1);
// tD格式:07/15/21
String str2 = String.format("%tD", date);
System.out.println("tD格式: "+str2);
// tc格式:星期四 七月 15 19:05:58 CST 2021
String str3 = String.format("%tc", date);
System.out.println("tc格式: "+str3);
// tr格式:07:05:58 下午
String str4 = String.format("%tr", date);
System.out.println("tr格式: "+str4);
  • 数字格式化
// 长度为5的字符串|  123|
// 右对齐|123  |
System.out.println(String.format("长度为5的字符串|%5d|", 123));
System.out.println(String.format("右对齐|%-5d|", 123));

// 33的8进制结果041
// 33的8进制结果0x21
System.out.println(String.format("33的8进制结果%#o", 33));
System.out.println(String.format("33的8进制结果%#x", 33));

// 我是正数+1
// 我是负数-1
System.out.println(String.format("我是正数%+d", 1));
System.out.println(String.format("我是负数%+d", -1));

// 我是正数,没有括号1
// 我是负数,有括号(1)
System.out.println(String.format("我是正数,没有括号%(d", 1));
System.out.println(String.format("我是负数,有括号%(d", -1));

// 我是正数00123
System.out.println(String.format("我是正数%05d", 123));

// 这是一个金额123,456,789
System.out.println(String.format("这是一个金额%,d", 123456789));
  • 常规格式化
// 字母x大写:X
String str1 = String.format("字母x大写:%c",'X');
System.out.println(str1);

// 12+34的结果是:46
System.out.println(String.format("12+34的结果是:%d", 12+34));

// n取两位小数点:3.14
System.out.println(String.format("n取两位小数点:%.2f", Math.PI));

// 2<3的结果:true
System.out.println(String.format("2<3的结果:%b", 2<3));

// 1200000.1用科学计数法表示:1.200000e+06
System.out.println(String.format("1200000.1用科学计数法表示:%e", 1200000.1));

// 灵感1%,汗水99%
System.out.println(String.format("灵感%d%%,汗水%d%%", 1,99));

3 集合

HashMap

  • 创建映射关系
//Map<key, value> 相当于key是键(地址),value是值(地址里的值)
Map<Integer, String> map = new HashMap<>();
  • put(k, v)函数,将键值送入映射
//输入,将键为1,值为one送入hashMap
map.put(1, "one");
map.put(2, "two");
System.out.println(map);

//输出
{1=one, 2=two}
  • get(k)函数
//得到键为1的值one
System.out.println(map.get(1));
  • map(k)函数
//map的长度,2
System.out.println(map.size());
  • idEmpty()函数
//判断map是否为空,false
System.out.println(map.isEmpty());
  • containsKey(k),containsValue(k)函数
//判断映射中是否有某个键为2,若有,返回true
System.out.println(map.containsKey(2));

//判断映射中是否有某个值为two,若有,返回true
System.out.println(map.containsValue("two"));
  • putAll()函数
//新建一个映射关系map1
Map<Integer, String> map1 = new HashMap<>();
map1.put(3, "three");
map1.put(4, "four");

//将map1中所有键值送入map中
map.putAll(map1);
System.out.println(map);

//输出
{1=one, 2=two, 3=three, 4=four}

  • remove(k)函数
//移除映射中的键值
map.remove(2);
System.out.println(map);

//输出
{1=one, 3=three, 4=four}
  • keySet(),values()函数
//只返回键,不输出值
System.out.println(map.keySet());
//输出
[1, 3, 4, 5]

//返回所有的值
System.out.println(map.values());
//输出
[one, three, four, five]
  • equals()函数
//判断两个映射是否相等
Map<Integer, String> map2 = new HashMap<>();
map1.put(3, "three");
map1.put(4, "four");
//map2.put(5, "five");

//比较指定的对象与此映射是否相等(判断两个映射是否完全相同,是就返回true)
System.out.println(map1.equals(map2));
  • clear()函数
//清除所有映射
map.clear();
System.out.println(map);

//输出
{}

ArrayList(动态数组)

Stack(栈)

Stack栈“先进后出”;
Stack本质是一个List,其具备List所有的方法;

Stack和ArrayList的区别

stack和ArrayList的最大区别是stack是线程安全的,而ArrayList不是线程安全的。所以,当涉及到多线程问题时,优先考虑使用stack。
因为stack实现了List接口,则可以将stack转换为list;
List<Integer> list = new ArrayList<Integer>(pre)

Stack方法

  • 初始化
    Stack stack = new Stack();
  • 判断Stack是否为空
    isEmpty()
  • 添加元素
    push(E item)
  • 获取栈顶值,元素不出栈(栈为空时抛异常)
    peek()
    stack调用peek后,item还是在栈中的,并未被移除,然后在调用peek时要判断stack中是否有元素,否则会引发异常。
  • 是否存在obj
    search(Object obj)
    返回值为int,若存在,返回值为obj距离栈顶的位置,若不存在,返回-1
  • 移除栈顶
    pop()
    此方法是移除栈顶的元素,并且返回值是移除的item

4 常用函数

获取当前时间

  • System.currentTimeMillis():获取当前的总毫秒数
  • Date:获取当前日期
  • SimpleDateFormat:按指定格式获取当前日期
public class demo {
    public static void main(String[] args) {
        //总毫秒数  从1970年1月1日开始计算
        long totalMilisSeconds = System.currentTimeMillis();
        //总秒数
        long totalSeconds = totalMilisSeconds / 1000;
        //当前秒数
        long currentSeconds = totalSeconds % 60;
        //总分钟
        long totalMinutes = totalSeconds / 60;
        //当前分钟
        long currentMinutes = totalMinutes % 60;
        //总小时(中国时区需加8小时)
        long totalHours = totalMinutes / 60 + 8;
        //当前小时
        long currentHours = totalHours % 24;
        //总天数
        long totalDays = totalHours / 24;
        Date date = new Date();
        System.out.println("总毫秒数:" + totalMilisSeconds);
        System.out.println("总秒数:" + totalSeconds);
        System.out.println("总分钟数:" + totalMinutes);
        System.out.println("总小时:" + totalHours);
        System.out.println("当前秒:" + currentSeconds);
        System.out.println("当前分钟数:" + currentMinutes);
        System.out.println("当前小时:" + currentHours);
        System.out.println("总天数:" + totalDays);
        SimpleDateFormat sdFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(date);
        System.out.println(sdFormatter.format(date));
    }
}

// 输出
总毫秒数:1629090995569
总秒数:1629090995
总分钟数:27151516
总小时:452533
当前秒:35
当前分钟数:16
当前小时:13
总天数:18855
Mon Aug 16 13:16:35 CST 2021
2021-08-16 13:16:35

Math.min

  • Math.min(a, b);
    返回值为小的那个数,
    1)a,b必须是同一类型的数据,返回值类型根据a,b的类型而定。
    2)a,b可接受double、float、int、long四种类型。

5 常用关键字

String、StringBuilder以及StringBuffer

1)String类

String类是final类,异味这String类不能继承。一旦一个String对象对创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象对销毁。

String a = "123";
a = "456";

在这里插入图片描述
可以看出来,再次给a赋值时,并不是对原来堆中实例对象进行重新赋值,而是生成一个新的实例对象,并且指向“456”这个字符串,a则指向最新生成的实例对象,之前的实例对象仍然存在,如果没有被再次引用,则会被垃圾回收。
对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象

2)String str = "hello world"和String str = new String(“hello world”)区别
public class demo {        
    public static void main(String[] args) {
        String str1 = "hello world";
        String str2 = new String("hello world");
        String str3 = "hello world";
        String str4 = new String("hello world");
         
        System.out.println(str1==str2);
        System.out.println(str1==str3);
        System.out.println(str2==str4);
    }
}

// 输出
false
true
false

class文件中有一部分 来存储编译期间生成的 字面常量以及符号引用,这部分叫做class文件常量池,在运行期间对应着方法区的运行时常量池。
  因此在上述代码中,String str1 = “hello world”;和String str3 = “hello world”; 都在编译期间生成了 字面常量和符号引用,运行期间字面常量"hello world"被存储在运行时常量池(当然只保存了一份)。通过这种方式来将String对象跟引用绑定的话,JVM执行引擎会先在运行时常量池查找是否存在相同的字面常量,如果存在,则直接将引用指向已经存在的字面常量;否则在运行时常量池开辟一个空间来存储该字面常量,并将引用指向该字面常量。
  众所周知,通过new关键字来生成对象是在堆区进行的,而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的。因此通过new来创建对象,创建出的一定是不同的对象,即使字符串的内容是相同的。

2)StringBuilder
public class demo {        
    public static void main(String[] args) {
        String string = "";
        for(int i=0;i<10000;i++){
            string += "hello";
        }
    }
}

这句 string += “hello”;的过程相当于将原有的string变量指向的对象内容取出与"hello"作字符串相加操作再存进另一个新的String对象当中,再让string变量指向新生成的对象。
  实际上,string+="hello"的操作事实上会自动被JVM优化成:(其实还是有点差距)
StringBuilder str = new StringBuilder(string);
str.append("hello");
str.toString();

public class demo {         
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<10000;i++){
            stringBuilder.append("hello");
        }
    }
}

反编译字节码文件得到,并且new操作只进行了一次,也就是说只生成了一个对象,append操作是在原有对象的基础上进行的。因此在循环了10000次之后,这段代码所占的资源要比上面小得多。

3)StringBuffer

查看源代码可知,StringBuilder和StringBuffer类拥有的成员属性以及成员方法基本相同,区别是StringBuffer类的成员方法前面多了一个关键字:synchronized,不用多说,这个关键字是在多线程访问时起到安全保护作用的,也就是说StringBuffer是线程安全的。

4)不同场景三个类的性能测试
public class demo {
        private static final int time = 50000;
        public static void main(String[] args) {
            testString();
            testStringBuffer();
            testStringBuilder();
            test1String();
            test2String();
        }
        
        public static void testString () {
            String s="";
            long begin = System.currentTimeMillis();
            for(int i=0; i<time; i++){
                s += "java";
            }
            long over = System.currentTimeMillis();
            System.out.println("操作"+s.getClass().getName()+"类型使用的时间为:"+(over-begin)+"毫秒");
        }
        
        public static void testStringBuffer () {
            StringBuffer sb = new StringBuffer();
            long begin = System.currentTimeMillis();
            for(int i=0; i<time; i++){
                sb.append("java");
            }
            long over = System.currentTimeMillis();
            System.out.println("操作"+sb.getClass().getName()+"类型使用的时间为:"+(over-begin)+"毫秒");
        }

        public static void testStringBuilder () {
            StringBuilder sb = new StringBuilder();
            long begin = System.currentTimeMillis();
            for(int i=0; i<time; i++){
                sb.append("java");
            }
            long over = System.currentTimeMillis();
            System.out.println("操作"+sb.getClass().getName()+"类型使用的时间为:"+(over-begin)+"毫秒");
        }

        public static void test1String () {
            long begin = System.currentTimeMillis();
            for(int i=0; i<time; i++){
                String s = "I"+"love"+"java";
            }
            long over = System.currentTimeMillis();
            System.out.println("字符串直接相加操作:"+(over-begin)+"毫秒");
        }

        public static void test2String () {
            String s1 ="I";
            String s2 = "love";
            String s3 = "java";
            long begin = System.currentTimeMillis();
            for(int i=0; i<time; i++){
                String s = s1+s2+s3;
            }
            long over = System.currentTimeMillis();
            System.out.println("字符串间接相加操作:"+(over-begin)+"毫秒");
        }
}

// 输出
操作java.lang.String类型使用的时间为:3765毫秒
操作java.lang.StringBuffer类型使用的时间为:2毫秒
操作java.lang.StringBuilder类型使用的时间为:1毫秒
字符串直接相加操作:1毫秒
字符串间接相加操作:5毫秒
  • 对于直接相加字符串,效率很高,因为在编译器便确定了它的值,也就是说形如"I"+“love”+“java”; 的字符串相加,在编译期间便被优化成了"Ilovejava"。
  • 对于间接相加(即包含字符串引用),形如s1+s2+s3; 效率要比直接相加低,因为在编译器不会对引用变量进行优化。
  • String、StringBuilder、StringBuffer三者的执行效率:StringBuilder > StringBuffer > String
    当然这个是相对的,不一定在所有情况下都是这样。比如String str = “hello”+ "world"的效率就比 StringBuilder st = new StringBuilder().append(“hello”).append(“world”)要高。

因此,这三个类是各有利弊,应当根据不同的情况来进行选择使用:

  • 当字符串相加操作或者改动较少的情况下,建议使用 String str="hello"这种形式;
  • 当字符串相加操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值