写在前面
我之前一直是以Golang为主语言的,最近开始转Java,包括平时刷题(欢迎来互粉哈: 千杉沐雪的力扣)的语言也改为使用Java。
在转语言的过程中,总避免不了要频繁地查基本的语法和一些常见函数操作。为了方便其他也有类似需要的朋友,我特此将我记的一些笔记重新梳理后发上来分享。
本文主要目标:
- 提供常用工具类的介绍,如:字符串,日期,随机数,正则等;
- 提供常见集合的介绍和操作,如:List,Map,堆栈等;
- 介绍一些Java与其他语言可能不一样的语法,如:数组操作,可变长参数等;
常用类
String类
基本知识
java中所有的字符串值都是用String类的实例实现,比如: String str = "abc";
等价于String str = new String(new char[]{'a','b','c'});
通过String类的函数和构造函数,可以实现char[], byte[]和String的互转。
注意事项
- 字符串本身是常量,在创建后不能更改
- 判断内容相等需要用equals判断(默认是比较地址,但是String类重写了equals方法为比较内容),直接用==还是比较地址,不能比较内容
其他功能
- 替换:
"hello".replace("l", "k")
- 去除字符串的两端空格:
" hello ".trim() => "hello"
- 字典序排序比较 —— 比较第一个不相等的字符做减法:
"habc".compareTo("hz")
,相当于'a'-'z'=-25
String和Int互转
- Int转字符串
System.out.println(String.valueOf(123));
System.out.println(123+"");
- 字符串转Int
System.out.println(Integer.parseInt(“123"));
StringBuffer/StringBuilder类 - 可变长字符串
分类
- StringBuffer 线程安全的可变字符串
- StringBuilder 单线程场景下的可变字符串,所有操作完全一样
有capacity()和length()两个概念:空对象的容量为16,长度为0
背景
一个长字符串拼接时,由于字符串不可更改,这个过程中会生成一大堆String对象
String a = "";
for(int i=0;i<10;i++){
a += i;
}
使用StringBuffer/StringBuilder在拼接(append)过程中使用同一对象,内存地址不变!
常用操作
StringBuffer sb = new StringBuffer();
sb.append("123").append("456"); // 追加
sb.insert(5, “hi”) // 在第5个字符之后插入
System.out.println(sb); // “12345hi6”
StringBuffer/StringBuilder和String的互转
- String => StringBuffer:创建一个空对象,append String进去即可
- StringBuffer => String:sb.toString() 方法
作为形参使用
- String作为形参要当做基本类型,复制值;
- StringBuffer即为普通的引用类型,形参会改变;
日期类 Date
获取当前时间戳
new Date().getTime(); // 毫秒,除以1000即是秒
日期转字符串 - 需要用到SimpleDateFormat类
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
System.out.println(sdf.format(d));
字符串转日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
try {
Date d2 = sdf.parse("2021-08-08 22:08:04");
} catch (ParseException e) {
e.printStackTrace();
}
随机数 Random
使用默认随机种子(当前毫秒时间戳):Random r = new Random();
使用随机种子(相同种子生成相同随机数序列):Random r = new Random( int seed );
获取随机数:r.nextInt(n); // 返回[0,n)范围内的随机数
正则表达式 Pattern/Matcher
基本用法
用字符串的方法即可,判断目标字符串是否满足正则表达式/按照正则表达式替换
// 示例的正则,20xx年份
String regex = "20\\d\\d";
// 1. 基本用法,判断是否符合正则的格式
System.out.println("2019".matches(regex)); // true
进阶用法
遍历目标字符串中所有满足正则表达式的子串 和 替换操作
// 1. 依次找到所有符合条件的字符串并输出
Matcher m = Pattern.compile(regex).matcher("2033,2088,1977,哈哈");
while (m.find()) {
System.out.println(m.group() + "子串的起始位置:" + m.start() + ",其结束位置:" + m.end());
}
// 2.1 正则匹配后替换,用matcher
System.out.println(m.replaceAll("[%year%]"));
Integer类
int类型的最大值,最小值(做比较时常用):Integer.MAX_VALUE, Integer.MIN_VALUE
Math的各类操作:
- 最大/最小/绝对值(支持int,float,double等各数值类型):
Math.max(a,b);
Math.min(a,b);
Math.abs(a);
- 求幂:
Math.pow(double a, double b) // a的b次方
- 求平方跟:
Math.sqrt(double a) // a开根号
集合/泛型
泛型
基础知识
- 是一种将明确类型的工作推迟到创建对象或者调用方法时才去明确的特殊类型。
- 避免了由于对集合使用Object代表任意类型,导致容器中对象类型前后不一致的问题:在编译时报错
- 只能用于引用类型,不能用于基本类型(用包装类替代,如Integer,Character代替int, char)。
- 一般在集合中使用,比如
List<Integer> l = new ArrayList<>();
根据指定泛型的具体类型的位置区分:
- 泛型类:
public class ObjectTool<T>{}
- 泛型接口:
public interface ObjectInt<T>{}
- 泛型方法:
public <T> objectMethod(T t){}
高级通配符
假设 Class Dog extends Animal {}
- ?:表示任意类
- ? extends E:向下限定,需要是E及其子类,比如
List<? extends Animal> l = new ArrayList<Dog>();
- ? super E:向上限定,需要是E及其父类,比如
List<? super Animal> l = new ArrayList<Animal>();
集合
为了方便对于多个对象的操作,提供了集合:和数组的区别在于,数组长度固定而集合长度可变。
集合只存储对象(用包装类,比如Integer,Character代替基础数据类型)。
可使用迭代器遍历集合:
Iterator<Integer> i = a.iterator();
while(i.hasNext()){
System.out.println(i.next());
}
集合介绍和常见操作
Map 字典
- 初始化操作
Map<Integer> m = new HashMap<>(); // 最常用,线程不安全的哈希表;线程安全可用ConcurrentHashMap
- 遍历操作
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
- 读写操作
// 正常写入
map.put(k,v);
// value为容器时写入空
map.putIfAbsent(key, new ArrayList<>());
// 正常读
map.get(k);
// 带默认值的读
map.getOrDefault(domTreat,0);
List 列表
- 初始化操作
List<String> result = new ArrayList<>(); // 基于数组实现的列表;基于链表实现LinkedList
- 遍历操作
for ( String tmp: l ) {
System.out.println(tmp);
}
- 读写操作
// 添加:
list.add(Object a);
list.set(int idx, Object a);
// 读:
list.get(int idx);
// 删除:
list.remove(Object a); list.remove(int idx);
// 排序:
Collections.sort(list, (a,b) -> a.compareTo(b))
// 逆序:
Collections.reverse(list);
Stack 栈
- 初始化操作
Stack<Integer> = new Stack<>(); // 基于Vector实现(List的一种,底层为数组)
- 入栈/出栈操作
T pop() // 出栈
push(T t) // 入栈
T peek() // 获取栈顶
Queue 队列
- 初始化操作
Queue<Integer> = new LinkedList<>(); // LinkedList实现了Queue接口
- 入队/出队操作
offer(T t) // 加入到队尾
T poll() // 队列头出队
T peek() // 获取队列头
PriorityQueue 堆
- 初始化操作
PriorityQueue<Integer> heap = new PriorityQueue<>((a,b)->a-b);
构造函数中为使用lambda表达式简化Comparator的写法
用于表明a和b的关系,如上所示就是小根堆
- 入堆/出堆操作
offer(T t) // 加入到堆中
T poll() // 删除堆顶
T peek() // 获取堆顶
其他语法
数组
- 声明和初始化
- 动态声明:给定长度并通过new关键字申请内存空间,系统用默认值初始化(比如int是0):
int[] a = new int[5];
- 通过字面量声明:
int[] t = new int[]{1,2,3,4};
可以简写为int []a = {1,2,3,4,5};
- 打印:
- 直接打印是出内存地址:
System.out.println(array);
- 一维数组可以用容器方法转换:
System.out.println(Arrays.toString(array));
- 赋值:数组为引用类型,存储在堆上,所以赋值是给的内存地址
int[] t = new int[5];
int[] s = t;
遍历:
for(int i=1;i<nums.length;i++) {
System.out.println(nums[i]);
}
可变长参数
参数长度可变化,在方法内获取参数时实际上就是数组
public void testParams(int... a){
for(int x:a){
System.out.println(a);
}
}
testParam(1,2,3,4,5); // 使用