零基础学习java------day13------常用API(Random,System,Date,DateFormate),正则(matches(匹配),split(分割),replaceAll(替换),Pattern结合matcher(获取)),集合
常用API
1.Random
1.1 Random类概述:
此类用于产生随机数,如果用相同的种子(构造方法中的参数)创建两个Random实例,则对每个实例进行相同方法调用序列,它们将生成并返回相同的数字序列
1.2 构造方法
public Random()
public Random(long sead)
注意:不含参的构造函数每次都使用当前时间作为种子,随机性更强,而含参的构造函数其实是伪随机(按照某种算法生成数据),更有可预见性
1.3 Random成员方法
public int nextInt()
public int nextInt(int n)
import java.util.Random; public class RandomDemo { public static void main(String[] args) { Random r = new Random();//默认以当前时间为种子 System.out.println(r.nextInt(100));//[0-100) System.out.println(r.nextInt());//在int范围随机获取一个数 } }
若种子相同,在相同的范围内,生成的随机数是相同的
Random r1 = new Random(123L); Random r2 = new Random(123L); for(int i=0;i<3;i++) { System.out.println(r1.nextInt(100)); System.out.println(r2.nextInt(100)); }
//运行结果82,82;50,50; 76,76,可见种子相同的两个对象产生的随机数是一样的
注意,此处产生的数是固定的,第一次一定产生82,第二次一定是50,数的产生是按某种算法得到,所以说含参数的构造方法是伪随机
2. System
2.1 system类概述
System类包含一些蝉蛹的类字段和方法。它不能被实例化
System.out.println(); new Scanner(System.in);
此处的out和in为输出流和输入流(具体以后了解)
2.2 成员方法
(1) public static void gc() : 垃圾回收
System.gc()可用于垃圾回收。当使用System.gc回收某个对象所占用的内存之前,通过要求程序调用适当的方法来清理资源。在没有明确指定资源清理的情况下,java提高了默认机制来清理该对象的资源,就是调用Object类的finalize()方法。finalize()方法的作用是释放一个对象占用的内存空间,当其释放空间时,会被JVM调用。而子类重写该方法,就可以清理对象占用的资源,该方法没有链式调用,所以必须手动实现。从程序的运行结果可以发现,执行System.gc()前,系统会自动调用finalize()放啊清楚对象战友的资源,通过super.finalize()方式可以实现从下到上的finalize()方法的调用,即先释放自己的资源,再去释放父类的资源。但是,不要在程序中频繁调用垃圾回收,因为每一次执行垃圾回收,jvm都会强制启动垃圾回收器运行,这会耗费更多的系统资源,会与正常的java程序运行争抢资源,只有在执行大量的对象的释放,才调用垃圾回收最好。
(2) public static voiid exit(int status): 退出系统
return是退出方法
public class SystemDemo { public static void main(String[] args) { for(int i=0;i<=10;i++) { if(i==2) { System.exit(0); // 0:正常的退出,1:非正常的退出 } System.out.println(i); } } } // 运行结果:0 1
(3)public static long currentTimeMillis() : 获取当前时间的毫秒值,其相对值为1970年1月1日0点0分0秒
System.nanoTime()为纳米级(尽量不要使用纳秒计算时间,只用于生成序列号)
long s = System.currentTimeMillis(); System.out.println(s); System.out.println(s/1000/60/60/24/365); //运行结果: 1566131641625 //此值表示如今相对1970年经历的毫秒值 49 //此值表示如今相对1970年经历的年份
此方法可用于查看某段代码或方法执行所需要的时间
(4)public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 从一个数组某个位置拷贝一些元素至另一个数组中
src:原数组 srcPos:从原数组的哪个位置开始拷贝 dest:目标数组
destPost:拷贝到目标数组的哪个位置 length:拷贝长度
int[] arr = {1,2,3,4,5,6,7,8}; int[] arr1 = new int[6]; System.arraycopy(arr,2,arr1,2,4); System.out.println(arr1);//[I@279f2327 System.out.println(Arrays.toString(arr1));//[0, 0, 3, 4, 5, 6] 此处Arrays重写了toString方法
// 运行结果:
[I@279f2327
[0, 0, 3, 4, 5, 6]
3. Date
3.1 Date类的概述:
类date表示特定的瞬间,精确到毫秒
3.2 构造方法:
public Date() 得到当前时间的一个对象
public Date(long date) 得到是date 毫秒所代表时间的一个对象
案例
import java.util.Date; public class DateDemo { public static void main(String[] args) { Date now = new Date(); System.out.println(now); //Sun Aug 18 21:11:50 CST 2019 Date d1 = new Date(0); System.out.println(d1);//Thu Jan 01 08:00:00 CST 1970 System.out.println(System.currentTimeMillis());//1566134241057 Date d2 = new Date(1566134241057L); System.out.println(d2); } }
3.3 成员方法:
public long getTime() 获取该时间对应的毫秒值
public void setTime(long time) 将时间设置为time 所代表的时间
System.out.println(d1.getTime());//0
Date now = new Date();//Sun Aug 18 21:25:27 CST 2019 now.setTime(0);//将现在的时间设置成毫秒值为0的时间 System.out.println(now);Thu Jan 01 08:00:00 CST 1970
4. DateFormat
(1) DateFormat类概述
Dateformat是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间,由于其是抽象类,所以使用它的子类SimpleDateFormat
(2) SimpleDateFormat构造方法
public SimpleDateFormat() :构造一个时间对象(date转为字符串)
public SimpleDateFormat(String pattern) 构造一个特定模式的时间对象
(3) 成员方法
public final String format(Date date) : 将Date类型的时间格式化
public Date parse(String source) :将String类型转为Date类型(字符串不能转为毫秒值,但Date类型可以,这样就可以间接对String类型时间及进行计算)
案例
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleDateFormatDemo { public static void main(String[] args) throws ParseException { Date d1 = new Date(); System.out.println(d1);//Sun Aug 18 23:05:46 CST 2019 SimpleDateFormat sdf1 = new SimpleDateFormat(); System.out.println(sdf1.format(d1)); // 2019/8/18 下午11:05 // 年月日时分秒 SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//此处也可写成别的形式(如HH:mm yyyy/MM-/dd) System.out.println(sdf2.format(d1)); //2019-08-18 23:05:46 String dateStr = "2019/8/18 22:15"; SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy/M/dd HH:mm"); //此处的pattern参数的模式要和待解析字符串时间模式一致 // 将字符串转译成Date类型 Date d2 =sdf3.parse(dateStr); System.out.println(d2);//Sun Aug 18 22:15:00 CST 2019 } }
注意:把字符串转成日期的时候,要注意字符串的日期格式一定要和构造方法中的Pattern保持一致,此外要处理异常
练习
将2014/05/03 12:12:12 转成 12:12:12 2014/05/03
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class Exer1 { public static void main(String[] args) throws ParseException { // 创建一个特定模式的时间对象 SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); String strDate = "2014/05/03 12:12:12"; // 将字符串类型转译成Date类型 Date d = sdf1.parse(strDate); System.out.println(new SimpleDateFormat("HH:mm:ss yyyy-M-dd").format(d)); } }
5. 正则表达式(regex,Regular expression)
正则表达式是指用一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串,其实就是一种规则,有直接特殊的应用
(1) 匹配 matches
例1:检验QQ号码,要求必须是5-15位数字,不能以数字0开头
法一:不使用正则的解法
import java.util.Scanner; public class RegexDemo1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入您的QQ号:"); String qq = sc.nextLine(); boolean re = checkQQ(qq); if(re) { System.out.println("格式正确"); }else { System.out.println("格式不对,麻花腾司马"); } } // 创建匹配方法 public static boolean checkQQ(String qq) { if(qq.length()>=5 &&qq.length()<=15 ) { if(!qq.startsWith("0")) { for(int i=0;i<qq.length();i++) { if(!Character.isDigit(qq.charAt(i))) { // 判断输入的是否是数字 return false; } } return true; } return false; } return false; } }
发现这种方法很麻烦
法二; 正则(其他代码同上)
// 正则创建匹配方法 public static boolean checkQQ1(String qq) { return qq.matches("[1-9][0-9]{4,14}");
可见,正则会很方便
练习
匹配一个小数(整数)
// 法一 System.out.println(res.matches("(\\d+)|(\\d+\\.\\d+)")); //法二 System.out.println(res.matches("\\d+(\\.\\d+)?"));
匹配手机号
import java.util.Scanner; public class MobileRegex { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入您的手机号码:"); String mobile = sc.nextLine(); boolean res = matchMobile(mobile); if(res) { System.out.println("格式正确"); }else { System.out.println("格式不正确,请重新输入手机号"); } } public static boolean matchMobile(String mobile) { String regex = "1[34578]\\d{9}"; // 简单匹配规则
// 考虑更多的匹配规则
String regex = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(17[013678])|(18[0,5-9]))\\d{8}$";
return mobile.matches(regex); } }
匹配邮箱
String regex = "[a-zA-Z_0-9]{3,20}@\\w{2,9}(\\.[a-zA-Z]{2,5}){1,2}";
匹配身份证号
String regex = "^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
(2)分割 split
注意:split得到的是数组
public class SpilitDemo { public static void main(String[] args) { String str = "aa,bb,cc"; String[] str1 = str.split(","); System.out.println(str1); //[Ljava.lang.String;@279f2327 System.out.println(str1[0]); // aa System.out.println(str1[1]);// bb System.out.println(str1[2]);// cc } }
练习
有如下一个字符串:“19 89 76 3 65”,请写代码实现最终输出结果是:“3 19 65 76 89”
import java.util.Arrays; import com._51doit.javase.util.ArrayUtil; public class Exer2 { public static void main(String[] args) { String str1 = "19 89 76 3 65"; String[] str2 = str1.split(" "); int[] arr = new int[5]; // 得到int数组 for(int i=0;i<str2.length;i++) { arr[i] = Integer.valueOf(str2[i]); } Arrays.sort(arr); ArrayUtil.printArr(arr); String str = ""; // 转换成想要的格式 StringBuilder sb = new StringBuilder(); for(int i=0;i<arr.length;i++) { sb.append(arr[i]).append(" ");// 法一 str += arr[i] + " "; // 法二 } System.out.println(str); } }
(3)正则的替换功能 replaceAll
例
1.手机号码的替换
public class RegexDemo2 { public static void main(String[] args) { String mobile = "18512341235"; String re = mobile.replaceAll("(\\d{3})(\\d{4})(\\d{4})", "$1****$2"); System.out.println(re); } }
// 运行结果:185****1234
2. 敏感字的替换
模糊替换(在字符串中,括号内的有字符都会被替换)
String str = "老王傻逼,傻逼"; String re1 = str.replaceAll("[(王二傻)]", "*"); System.out.println(re1); // 运行结果:老**逼,*逼
精确替换
String str = "老王傻逼,傻逼"; String re1 = str.replaceAll("傻逼", "**"); System.out.println(re1); // 运行结果:老王**,**
(4)正则表达式的获取功能(Pattern和macher)
import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexDemo3 { public static void main(String[] args) { String str = "jin tian yao xia yu,da jia pa bu pa ? huang bu huang ?"; //1. 创建Pattern对象。传入一个正则表达式 Pattern p = Pattern.compile("\\b[a-zA-Z]{3}\\b"); //2. 调用p对象中的macher 获取匹配器对象 Matcher matcher = p.matcher(str); System.out.println(matcher.find());//true System.out.println(matcher.group());//jin System.out.println(matcher.find());//true System.out.println(matcher.group());//yao } }
注意,此处的matcher.group()不能单独使用,必须跟find一起使用,若只有matcher.group()则会报错,如下
System.out.println(matcher.group());
报错如下
集合
0. 前提:
为什么出现集合?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,java就提供了类集合。
数组和集合类同时容器,有何不同?
数组虽然也可以存储对象,但长度是固定的,而集合的长度是可变的
数组中可以存储基本数据类型,集合只能存储对象(基本数据类型只能通过包装类来实现)
集合类的特点
集合只用于存储对象,集合的长度是可变的,集合可以存储不同类型的对象
说明:虚线框表示接口
1.概述:
Collection接口是集合类的根接口,java中没有提供这个接口的直接实现类。但是却让其被继承产生了两个接口,就是Set和List。Set中不能包含重复的元素,List是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式。
Map是java.util包中的另一个接口,它和Collection接口没有关系,是相互独立的,但是都属于集合类的一部分。Map包含了key-value对。Map不能包含重复的key,但是可以包含相同的value
Iterator,所有的集合类都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含以下三种方法:
(1)hasNext()是否还有下一个元素
(2)next()返回下一个元素
(3)remove()删除当前元素
Collection 和Collections区别
Collection:单列集合的根接口
Collections:集合的工具类
2. Collection成员方法
2.1 元素操作
(1)boolean add(E e): 添加元素(E表示一个泛型,可以接收任何参数)
public class CollectionDemo { public static void main(String[] args) { Collection c = new ArrayList(); // 通过子类去实现父类接口,父类引用指向子类 c.add(123); c.add("112"); c.add(new Object()); System.out.println(c); // [123, 123, 112, java.lang.Object@279f2327] } } //运行结果:[123, 123, 112, java.lang.Object@279f2327]
(2)boolean remove(Object o): 移除元素
c.remove(123);//若有多个要移除的对象,只移除第一个 System.out.println(c);// [123, 112, java.lang.Object@279f2327] System.out.println(c.size());// 3
(3) void clear():清空集合
(4)boolean contains(Object o):是否包含
(5)boolean isEmpty():是否为空
(6)int size():集合中的元素的个数
2.2 集合操作
(1)boolean addAll(Collection c):添加所有
(2)boolean removeAll(Collection c):移除集合c中所包含的所有元素 (如c1.removeAll(c2),即移除c1中所有在c1中出现的元素)
(3)boolean containsAll(Collection c):是否全部包含
(4)boolean retainAll(Collection c):取两个集合的交集
案例
import java.util.ArrayList; import java.util.Collection; public class CollectionDemo1 { public static void main(String[] args) { Collection c1 = new ArrayList(); c1.add("大乔"); c1.add("小乔"); c1.add("周瑜"); // addAll Collection c2 = new ArrayList(); c2.add("曹操"); c2.add("典韦"); c2.add("吕布"); c1.addAll(c2); System.out.println(c1);// [大乔, 小乔, 周瑜, 曹操, 典韦, 吕布] // containAll System.out.println(c1.containsAll(c2));//true // retainAll Collection c3 = new ArrayList(); c3.add("曹操"); c3.add("典韦"); c3.add("吕布"); c3.add("猪八戒"); c1.retainAll(c3); System.out.println(c1);//[曹操, 典韦, 吕布] // removeAll c3.removeAll(c1); System.out.println(c3);//[猪八戒] } }
3. Collection的遍历
Collection成员方法
(1)Object[ ] toArray():
把集合转成数组,可以实现集合的遍历
public class CollectionDemo2 { public static void main(String[] args) { Collection c1 = new ArrayList(); c1.add("曹操"); c1.add("典韦"); c1.add("吕布"); c1.add("猪八戒"); Object[] array = c1.toArray(); //小技巧,左边可直接通过crtrl+1,并选择带local项的选项 for(int i=0;i<array.length;i++) { System.out.println(array[i]); } } }
(2)Iterator iterator()
迭代器,集合的专用遍历方式
Iterator it = c1.iterator(); while(it.hasNext()) { System.out.println(it.next()); }
说明:
Iterator接口概述:对collection进行迭代的迭代器,依赖于集合而存在,其常用的成员方法为:
boolean hasNext():是否还有下一个元素
E next():返回下一个元素
4. List接口
4.1 概述:
有序的collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确的控制,用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素
与set不同,列表通常允许重复的元素
4.2 List接口成员方法
(1)void add(int index, E element) :插入
public class ListDemo { public static void main(String[] args) { List list = new ArrayList(); list.add(0,12); //list.add(2,23);此处若跳过索引值1直接在2的位置添加数据会报错 list.add(1,15); System.out.println(list);//[12, 15] } }
注意:List中添加元素要按索引顺序添加
(2)E remove(int index):按索引移除
public class ListDemo { public static void main(String[] args) { List list = new ArrayList(); list.add(0,12); list.add(1,13); list.add(2,18); list.add(3,33); System.out.println(list);//[12, 13, 18, 33] list.remove(2); System.out.println(list);//[12, 13, 33] } }
注意:remove移除元素后,后面的元素会向前补缺,若在原有索引位置添加元素,则原有的索引值会被依次顶到后面
(3)E get(int index):按索引获取元素
(4)E set(int index, E element):替换
(5)ListIterator listIterator():
43 list中的遍历:
(1)第一种(listIterator),依次向后遍历(hasNext)
public class ListDemo { public static void main(String[] args) { List list = new ArrayList(); list.add(0,12); list.add(1,13); list.add(2,18); list.add(3,33); ListIterator listIt = list.listIterator(); while(listIt.hasNext()) { System.out.println(listIt.next()); } } }
向前遍历(hasPrevious())
注意:往前遍历必须配合往后遍历使用(即指针的位置要在最后面才能进行遍历,在0处相当于前面没有元素)
while(listIt.hasNext()) { System.out.println(listIt.next()); } while(listIt.hasPrevious()) { System.out.println(listIt.previous()); }
(2)for循环结合get() (列表特有的方法)
for(int i=0,i<listIt.size();i++){ System.out.println(listIt.get(i)) }
(3)第三种,使用数组(将集合转为数组toArray)
(4)第四种,使用Iterator接口
这两种方法同上面collection遍历一样
(5)forearch(增强循环)
for(Object obj:list) { System.out.println(obj); }
练习
1. String str = "张三,18,男;李四,39,女;王五,36,男",把这个字符串中分理出三个Person对象,存到一个集合中去
import java.util.ArrayList; import java.util.List; public class ListExer { public static void main(String[] args) { String str = "张三,18,男;李四,39,女;王五,36,男"; String[] arr = str.split(";"); List<Person> list = new ArrayList<>(); for(int i=0;i<arr.length;i++) { String s = arr[i]; String[] arr1 = s.split(","); String name = arr1[0]; int age = Integer.parseInt(arr1[1]); char gender = arr1[2].charAt(0); Person p = new Person(name,age,gender); list.add(p); } System.out.println(list); } } class Person{ String name; int age; char gender; public Person(String name, int age, char gender) { super(); this.name = name; this.age = age; this.gender = gender; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", gender=" + gender + "]"; } }
// 运行结果 [Person [name=张三, age=18, gender=男], Person [name=李四, age=39, gender=女], Person [name=王五, age=36, gender=男]]
2. 获取persons中年龄大于20岁的对象(代码中),放到新的集合当中去
public class ListExer { public static void main(String[] args) { List<Person> persons = new LinkedList<>(); persons.add(new Person("张三",18,'男')); persons.add(new Person("李四",17,'男')); persons.add(new Person("王二",28,'男')); persons.add(new Person("麻子",38,'男')); persons.add(new Person("张三",18,'男')); LinkedList<Person> ps = new LinkedList<>(); for(int i=0;i<persons.size();i++) { Person p = persons.get(i); if(p!=null && p.age>20) { ps.add(p); } } System.out.println(ps); } } class Person{ String name; int age; char gender; public Person(String name, int age, char gender) { super(); this.name = name; this.age = age; this.gender = gender; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", gender=" + gender + "]"; } }
3.一个集合中有多个person对象,去掉属性一致的对象
注意:需要重写toString方法,不然比较的是地址值
法一:选择排序的思路
public class ListExer { public static void main(String[] args) { List<Person> persons = new LinkedList<>(); persons.add(new Person("张三",18,'男')); persons.add(new Person("李四",17,'男')); persons.add(new Person("张三",18,'男')); persons.add(new Person("张三",18,'男')); persons.add(new Person("张三",18,'男')); persons.add(new Person("王二",28,'男')); persons.add(new Person("麻子",38,'男')); persons.add(new Person("张三",18,'男')); LinkedList<Person> ps = new LinkedList<>(); for(int i=0;i<persons.size()-1;i++) { for(int j=i+1;j<persons.size();j++) { if(persons.get(i).equals(persons.get(j))) { persons.remove(j); j--; //此处j一定要执行此操作,不然当j处的元素被移除后,其索引要向前移一位,这样就会有些元素不被考虑到 } } } System.out.println(persons); } } class Person{ String name; int age; char gender; public Person(String name, int age, char gender) { super(); this.name = name; this.age = age; this.gender = gender; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", gender=" + gender + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + gender; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (gender != other.gender) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
法二:创建一个新的集合,当新集合中不包含原集合元素时,就往里面添加元素(其他代码同上)
for(int i=0;i<persons.size()-1;i++) { if(!ps.contains(persons.get(i))) { ps.add(persons.get(i)); } }
System.out.println(ps);
4.4 LinkedList
(1)ArrayList和LinkedList的区别
Arraylist:底层是数组,增删慢,查询快
LinkedList:底层是链表,增删快,查询慢
(2)LinkedList中特有的方法
addFirst/addLast: 添加头/添加尾
getFirst/getLast: 获取头/获取尾
removeFirst/removeLast: 移除头/移除尾
注意:不能使用多态调用(这些方法都是linkedList子类独有的方法)