常见cmd命令
dir 查看当前路径下全部内容
cls 清屏
exit 退出
ipconfig 查看本地ip地址
ping 某IPAddress 检查网络是否连通
Path环境变量
用来配置命令的路径的,这样可以在命令行窗口中的任何位置直接使用这些命令(javac,java,javap)
先配置JAVA_HOME,再在Path中引用JAVA_HOME;或者直接在Path中引用,但是不推荐
告诉操作系统JDK提供的javac(编译)、java(执行)命令安装到了哪个位置
IDEA结构
project–>module–>package–>class
IDEA快捷键
ctrl+/ 单行注释
shift+ctrl+/ 多行注释
Ctrl+Alt+L 格式化代码
Ctrl+Alt+M 抽取方法
Ctrl+Alt+T 加try catch,while等
shift+F6 变量重命名
shift+ctrl+/多行注释
ctrl + alt+ v 或者.var 自动补全左侧声明变量
Ctrl+Alt+h idea中查看方法被谁调用
Edit-->Find/Find in Path idea全局搜索关键字
Ctrl+Alt+B 进入方法实现类
Alt+enter lambda表达式与匿名内部类转换
转意符
\n 换行
\t 空格
运算符
//赋值运算符
int i += j; //将i+j赋值给i
//逻辑非"!":!flase = true;
//逻辑异或: 必须两个不同结果才是true
false ^ true //true
true ^ true //false
//短路逻辑运算符
&& 短路与 判断结果与"&"相同.过程是左边是false,右边则不执行
|| 短路或 判断结果与"|"相同.过程是左边是true,右边则不执行
//三元运算符
int score = 90;
String result = score >= 60 ? "通过":"挂科";
//三元运算符(最值判断)
int i = 10;
int j = 20;
int k = 30;
int max = i >j ? (i>k ? i : k) : (j>k ? j :k);
分支结构
//Switch分支
//if适合做区间匹配,Switch适合做值匹配
//表达式只能是byte,short,int,char,JDK5枚举,JKD7String,不支持double,float,long
//case给出的值不能重复,不能是变量
//不要忘记写break,否则会出现穿透现象
String weekday = "Monday";
switch (weekday){
case "Monday":
System.out.println("working");
break;
case "Friday":
System.out.println("working again");
break;
default:
System.out.println("weekend");
}
//如果代码执行到没有写break的case块,执行完后将直接进行下一个case块执行代码(而且不会进行任何匹配),直到遇到break才跳出分支,这就是switch的穿透性
int month = 1;
switch (month){
case 1:
case 3:
case 5:
case 7:
case 10:
case 12:
System.out.println( month + "month = " + "31 days");
break;
case 2:
System.out.println( month + "month = " + "28 or 29 days");
break;
case 4:
case 6:
case 9:
case 11:
System.out.println( month + "month = " + "30 days");
break;
default:
System.out.println("data is error");
}
循环结构
//for循环针对已知循环次数;while循环针对不确定次数循环
//0.1mm的纸张,折叠多少次超过珠峰高度
double peak = 8848880;
double paper = 0.1;
int count = 0;
while (paper <= peak ){
paper*=2;
count++;
}
System.out.println("paper = " + paper/2);
System.out.println("count = " + count);
//死循环
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println("请输入密码");
int input = scanner.nextInt();
if(input == 520){
System.out.println("密码正确");
break;
}else{
System.out.println("密码错误");
}
}
//break 跳出并结束当前所在循环的执行
//continue 只能再循环中进行使用,用于跳出当前循环的当次执行,进入下一次循环
枚举
//枚举定义
public enum Season {
SPRING,SUMMER,AUTUMN,WINTER;
}
//枚举使用
public static void season(Season se){
switch (se){
case SPRING:
System.out.println("Spring");
break;
case SUMMER:
System.out.println("SUMMER");
break;
case AUTUMN:
System.out.println("AUTUMN");
break;
case WINTER:
System.out.println("WINTER");
break;
}
}
方法
//基本数据类型和引用数据类型参数传递都是值传递
//基本数据类型参数传递存储的数据值
//引用数据类型参数传递储存的地址值
//方法重载
//同一个类中,多个方法的名称相同,形参列表不同
//对于相似功能业务场景:可读性好,方法名称相同提示是同一类型的功能,通过形参不同实现功能差异化的选择,这是一种专业化的代码设计
//只要是同一个类中,方法名相同,形参列表不同,(修饰符,返回值类型,形参名称都无所谓)
public static void get(){
get(1, "王浩");
}
public static void get(String str){
get(1, str);
}
public static void get(int a, String str){
System.out.println("第"+ a + "名,姓名" + str);
}
//return 跳出并立即结束当前所在方法的执行
//break 跳出并结束当前所在循环的执行
//continue 结束当前所在循环的当次继续,进入下一次执行
public static void chu(int a, int b){
if (b == 0){
System.out.println("除数不能为0");
return;
}
int c = a/b;
System.out.println(c);
}
面向对象
//属性 成员变量
//一般无需指定初始化值,存在默认值
public int age;
//自定义对象,引用对象,数组等在栈中存一个地址,指向堆中的对象
public class Car {
//封装
//成员变量使用private关键字修饰进行隐藏,private修饰后该成员变量就只能在当前类中访问
private String name;
private double price;
//提供public修饰的get和set方法暴露其取值和赋值
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
//无参构造器(默认的)
public Car(){}
//有参构造器
public Car(String name, double price){
//this代表当前对象Car
this.name = name;
this.price = price;
}
}
//成员变量:类中,方法外;有默认初始化值;随着对象的创建而存在,随着对象的消失而消失
//局部变量:常用于方法中;没有默认值,使用之前需要完成赋值;随着方法的调用而存在,随着方法的运行结束而消失
//继承
class Animal {
public String name ="父类成员变量";
}
class Wolf extends Animal {
public String name ="子类成员变量";
public void show(){
String name ="局部变量";
System.out.println(name);//局部变量
System.out.println(this.name);//子类成员变量
System.out.println(super.name);//父类成员变量
}
}
//继承,重写
class People {
private String name;
private String sex;
public People() {
}
public People(String name, String sex) {
this.name = name;
this.sex = sex;
}
public void show(){
}
}
class Student extends People {
public String name ="子类成员变量";
//重写方法加上Override
@Override
//重写方法的名称、形参列表必须与被重写方法的名称和形参列表一致
//私有方法不能被重写
//子类修饰符必须不小于父类
public void show(){
String name ="局部变量";
System.out.println(name);//局部变量
System.out.println(this.name);//子类成员变量
System.out.println(super.name);//父类成员变量
}
}
//继承,构造方法,super,this
class People {
private String name;
private String sex;
public People() {}
public People(String name){
this(name,"male");//借用兄弟构造器;this/super只能用一个
}
public People(String name, String sex) {
this.name = name;
this.sex = sex;
}
}
class Student extends People {
private String className;
public Student(){
super();//子类构造方法会默认调用父类空构造器
}
//子类构造方法,先初始化父类构造方法
public Student(String name, String sex, String className) {
super(name, sex);//初始化时调用父类构造器
this.className = className;
}
}
权限修饰符
权限修饰符(小-->大)
//private->缺省->protected->public
final
//final
//final修饰的类不能被继承,比如String
//final修饰的方法不能被重写
//final修饰的变量,有且只能被赋值一次,比如π,常量
//final修饰的引用数据类型,变量中存储的地址不能被改变,但是地址指向的对象内容可以改变
变量:
局部变量
成员变量
静态成员变量
实例成员变量
abstract
//抽象类
public abstract class Animal {
//抽象方法
public abstract String getName();
//抽象类不能创建对象
//抽象类可以写一般方法
//不能用abstract修饰变量、代码块、构造器
}
//Alt+回车:生成需要重写的抽象方法
public class Tight extends Animal{
@Override
public String getName() {
return null;
}
}
多态
ClassCastException
instanceof
//多态
//多态不能使用子类独有的方法
Animal animal = new Dog();
animal.run();
//强制类型转换
Dog dog = (Dog)animal;
dog.lookDoor();
//强制类型转换错误,运行时异常
//Exception in thread "main" java.lang.ClassCastException: com.benjamin.多态.Dog cannot be cast to com.benjamin.多态.Cat
//Cat cat = (Cat)animal;
//cat.run();
//如果animal是Cat的实例,返回true
if(animal instanceof Cat){
Cat cat = (Cat)animal;
cat.run();
}
接口
//规范合并,整合多个接口为同一个接口,便于子类实现
public interface Demo {
//接口可以定义常量和抽象类
//修饰符可以省略
//接口多继承
public static final String str = "";
String str1 = "";
public abstract void run();
void run1();
}
匿名内部类
//创建窗口
JFrame jFrame = new JFrame("登录界面");
//创建桌布
JPanel jPanel = new JPanel();
jFrame.add(jPanel);
//创建按钮对象
JButton jButton = new JButton("logon");
//匿名内部类
//抽象类AbstractAction直接实现抽象方法
jButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
//弹窗
JOptionPane.showMessageDialog(jButton,"logon successful");
}
});
//把按钮对象添加到桌布上
jPanel.add(jButton);
//展示窗口
jFrame.setSize(400,300);
jFrame.setLocationRelativeTo(null);
jFrame.setVisible(true);
String
char[] chars = {'a','中','1','A'};
String str1 = new String(chars);
System.out.println(str1);
byte[] bytes = {97,98,99,65,66,67};
String str2 = new String(bytes);
System.out.println(str2);
//双引号创建的字符串对象,在字符串常量池中存储同一个
//通过new构造器创建的字符串对象,在堆内存中分开存储
String str3 = new String("abc");
String str4 = new String("abc");
System.out.println(str3 == str4);//false
String str5 = "abc";
String str6 = "abc";
String str7 = "a"+"b"+"c";
String str8 = "ABC";
System.out.println(str5 == str6);//true
//Java存在编译优化机制,程序在编译时:"a"+"b"+"c"会直接转成"abc"
System.out.println(str5 == str7);//true
//equals
//基本数据类型比较时用==,引用类型使用equals
boolean f1 = str5.equals(str6);//true
System.out.println(f1);
boolean f2 = str5.equalsIgnoreCase(str8);//true
System.out.println(f2);
System.out.println(str5.length());//3
char a = str5.charAt(1);
System.out.println(a);//b
//遍历字符串中每个元素
for (int i=0; i<str5.length(); i++){
char ch = str5.charAt(i);
System.out.print(ch+"\t");//a b c
}
//把字符串转换成字符数组
char[] chars1 = str5.toCharArray();
//subString [0,3)
String str9 = "我爱你中国";
System.out.println(str9.substring(0, 3));//我爱你
System.out.println(str9.substring(3));//中国
//replace替换
System.out.println(str9.replace("我爱你", "***"));//***中国
//contains包含
System.out.println(str9.contains("中国"));//true
//split分割字符串
String str10 ="abc,icbc,hsbc";
String[] str11 = str10.split(",");//abc icbc hsbc
StringBuilder append(),reverse()
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
//链式编程,因为append()返回sb对象
sb.append("abc").append(1).append('a');
System.out.println(sb.toString());//abc1a
//反转
String string = sb.reverse().toString();
System.out.println(string);//a1cba
int[] arr1 = null;
int[] arr2 = {1,2,3,4};
int[] arr3 = {};
System.out.println(toString(arr1));
System.out.println(toString(arr2));
System.out.println(toString(arr3));
}
public static String toString(int[] arr){
if (arr!=null){
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length; i++) {
sb.append(arr[i]).append(i==arr.length-1 ? "":", ");
}
sb.append("]");
return sb.toString();
}else{
return null;
}
}
String和StringBuffer和StringBuilder的区别
String
String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间
不可变
==================================================================
StringBuffer
StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量
可变
线程安全
StringBuffer是单线程的,因为里面的方法都是被synchronized修饰了。所以它线程安全,但是效率自然就降低。
多线程操作字符串建议使用StringBuffer。
==================================================================
StringBuilder
可变,速度更快
线程不安全
StringBuilder不是单线程的,因为里面的方法没有被synchronized修饰了。所以它线程不安全,所以效率要更高。
单线程操作字符串建议使用StringBuilder
Object toString(),equals()
public class ObjectTesting extends Object{
private String name;
private int age;
//右键,generate...自动生产代码
@Override
public String toString() {
return "ObjectTesting{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ObjectTesting that = (ObjectTesting) o;
return age == that.age &&
Objects.equals(name, that.name);
}
}
Objects equals(),isNull()
String str1 = null;
String str2 = "";
//System.out.println(str1.equals(str2));//NullPointerException
//Objects.equals()更安全,当参数1为null,不会报NullPointerException
System.out.println(Objects.equals(str1, str2));//false
System.out.println(Objects.isNull(str1));//true//等同于obj == null
StringUtils.isBlank() 和 isEmpty()的使用
使用StringUtils.isBlank方法,它可以校验三种情况:
是否为null、
是否为""、
是否为空字符串(引号中间有空格)" "、制表符、换行符、换页符和回车
StringUtils.isEmpty("yyy") = false
StringUtils.isEmpty("") = true
StringUtils.isEmpty(" ") = false
StringUtils.isBlank("yyy") = false
StringUtils.isBlank("") = true
StringUtils.isBlank(" ") = true
Math
//取绝对值
System.out.println(Math.abs(-10.1));//10.1
//向上取整
System.out.println(Math.ceil(1.001));//2.0
//向下取整
System.out.println(Math.floor(2.99));//2.0
//指数次方
System.out.println(Math.pow(2, 3));//2^3=8
//四舍五入
System.out.println(Math.round(4.5));
System.out.println(Math.round(4.4));
//Math.random()生成[0.0 , 1.0)随机数
//求一个3~9随机整数
int num = (int)(Math.random()*7+3);
System.out.println(num);
BigDecimal
解决浮点型运算精度失真问题
Double 类型的加、减、乘 精确运算
double a = 0.1;
double b = 0.2;
double c = a+b;//0.30000000000000004
System.out.println(c);
//解决浮点型运算精度失真问题
BigDecimal b1 = BigDecimal.valueOf(a);
BigDecimal b2 = BigDecimal.valueOf(b);
BigDecimal b3 = b1.add(b2);
double d = b3.doubleValue();//0.3
System.out.println(d);
BigDecimal b4 = BigDecimal.valueOf(10.0);
BigDecimal b5 = BigDecimal.valueOf(3.0);
//BigDecimal是一定要精读运算的,divide(除数,保留几位小数,四舍五入等舍入模式)
BigDecimal b6 = b4.divide(b5,2,RoundingMode.HALF_UP);
System.out.println(b6.doubleValue());
/**
* 两个double类型数据的和
*/
private Double addDouble(Double pre1h, Double aDouble) {
BigDecimal b1 = BigDecimal.valueOf(pre1h);
BigDecimal b2 = BigDecimal.valueOf(aDouble);
BigDecimal b3 = b1.add(b2);
return b3.doubleValue();
}
/**
* 自定义对象数组中,double类型字段求和
*/
private Double sumPre(List<StationLiveHistory> dateHoursBefore) {
Double sum = dateHoursBefore.stream().map(temp -> temp.getPre1h())
.reduce(0.0, (result, element) -> result + element);
String dataFormat = String.format("%.2f", sum);
return Double.parseDouble(dataFormat);
}
包装类
int a = 1;
Integer b = 2;
Integer c = a;//自动装箱
int d = b;//自动拆箱
String str = "true";
boolean flag = Boolean.valueOf(str);//转换成boolean值
if(flag){
int e = Integer.valueOf("1");//转换成整数
System.out.println(e);
}
System
//System.exit(0);//退出当前JVM
long time = System.currentTimeMillis();//当前时间的毫秒值,从1970.01.01开始计算
int[] arr1 = {1,2,3,4,5,6,7,8};
int[] arr2 = {0,0,0,0,0};
//数组拷贝
System.arraycopy(arr1,2,arr2,0,4);
System.out.println(Arrays.toString(arr2));[3, 4, 5, 6, 0]
Date
SimpleDateFormat
Calendar
//代表系统此刻日期时间对象
Date date = new Date();//Thu Dec 02 23:27:28 CST 2021
System.out.println(date);
//获取时间毫秒值
long time = date.getTime();//1638458848145
System.out.println(time);
//另一种获取时间毫秒值,从1970年1月1号0点开始计算
long currentTime = System.currentTimeMillis();//1638458848145
System.out.println(currentTime);
//展示当前时间
Date date2 = new Date(currentTime);//Thu Dec 02 23:36:02 CST 2021
System.out.println(date2);
//展示当前时间往后推一个小时的时间
Date date3 = new Date();
date3.setTime(currentTime + 60*60*1000L);//Fri Dec 03 00:36:02 CST 2021
System.out.println(date3);
//格式化日期对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date3f = sdf.format(date3);//2021-12-03 00:47:55
System.out.println(date3f);
String cl = sdf.format(currentTime + 60*60*1000L);//2021-12-03 00:47:55
System.out.println(cl);
//2021-08-06 11:11:11往后2天14小时06秒的时间是
String str = "2021-08-06 11:11:11";
Date date4 = sdf.parse(str);
long date4l = date4.getTime()+(2L*24*60*60+14*60*60+6)*1000;
System.out.println(sdf.format(date4l));//2021-08-09 01:11:17
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
System.out.println(year);//2021
int mm = cal.get(Calendar.MONTH)+1;
System.out.println(mm);//12
int days = cal.get(Calendar.DAY_OF_YEAR);
System.out.println(days);//337
cal.add(Calendar.DAY_OF_YEAR,10);
Date d = cal.getTime();
System.out.println(d);//Mon Dec 13 23:43:17 CST 2021,10天后
long t2 = cal.getTimeInMillis();
System.out.println(t2);//1639410305199
JDK8 added LocalDate LocalTime LocalDateTime and so on
//JDK8
//获取本地年月日
LocalDate localDate = LocalDate.now();//2021-12-04
System.out.println(localDate);
int year = localDate.getYear();//2021
int month = localDate.getMonthValue();//12
int day = localDate.getDayOfMonth();//4
System.out.println("year: "+year+";month: "+month+";day: "+day);//year: 2021;month: 12;day: 4
int dayOfYear = localDate.getDayOfYear();//338
System.out.println(dayOfYear);
//星期
System.out.println(localDate.getDayOfWeek());//SATURDAY
System.out.println(localDate.getDayOfWeek().getValue());//6
//月份
System.out.println(localDate.getMonth());//DECEMBER
System.out.println(localDate.getMonth().getValue());//12
LocalDate bt = LocalDate.of(1989,12,30);
System.out.println(bt);//1990-01-01
//两个年月日差值
Period period = Period.between(bt,localDate);
System.out.println(period);//P31Y11M4D
System.out.println(period.getYears());//31
System.out.println(period.getMonths());//11
System.out.println(period.getDays());//4
System.out.println("时分秒");
//不可变对象,每次修改产生新对象
LocalTime localTime = LocalTime.now();//22:09:25.622
System.out.println(localTime);
System.out.println(localTime.minusHours(1));//1小时前,21:09:25.622
System.out.println(localTime.plusHours(2));//2小时后,00:09:25.622
LocalTime localTime2 = LocalTime.now();//22:09:25.622
System.out.println(localTime2);
System.out.println("时分秒");
//年月日时分秒
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);//2021-12-04T22:00:52.939
//判断今天是否你的生日
LocalDate birdate = LocalDate.of(1990,1,1);
LocalDate nowdate = LocalDate.now();
MonthDay birmd = MonthDay.of(birdate.getMonthValue(),birdate.getDayOfMonth());
MonthDay nowmd = MonthDay.from(nowdate);
System.out.println(nowmd.equals(birmd));//false
//时间戳
Instant instant = Instant.now();
System.out.println(instant);//2021-12-04T15:13:38.955Z UKT
Date date = Date.from(instant);
System.out.println(date);//Sat Dec 04 23:13:38 CST 2021
LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//正向、逆向格式化
System.out.println(dtf.format(localDateTime));//2021-12-04 23:24:12
System.out.println(localDateTime.format(dtf));//2021-12-04 23:24:12
//解析字符串时间
LocalDateTime localDateTime1 = LocalDateTime.parse("2019-11-11 11:30:30",dtf);
System.out.println(localDateTime1);//2019-11-11T11:30:30
//两个年月日时分秒差值
Duration duration = Duration.between(localDateTime1,localDateTime);
System.out.println(duration.toDays());//754
System.out.println(duration.toHours());//18108
System.out.println(duration.toMinutes());//1086490
System.out.println(duration.toNanos());//65189409799000000
// 本地日期时间对象:此刻的
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
// 生日时间
LocalDateTime birthDate = LocalDateTime.of(1990,10,1,
10,50,59);
System.out.println(birthDate);
System.out.println("相差的年数:" + ChronoUnit.YEARS.between(birthDate, today));
System.out.println("相差的月数:" + ChronoUnit.MONTHS.between(birthDate, today));
System.out.println("相差的周数:" + ChronoUnit.WEEKS.between(birthDate, today));
System.out.println("相差的天数:" + ChronoUnit.DAYS.between(birthDate, today));
System.out.println("相差的时数:" + ChronoUnit.HOURS.between(birthDate, today));
System.out.println("相差的分数:" + ChronoUnit.MINUTES.between(birthDate, today));
System.out.println("相差的秒数:" + ChronoUnit.SECONDS.between(birthDate, today));
System.out.println("相差的毫秒数:" + ChronoUnit.MILLIS.between(birthDate, today));
System.out.println("相差的微秒数:" + ChronoUnit.MICROS.between(birthDate, today));
System.out.println("相差的纳秒数:" + ChronoUnit.NANOS.between(birthDate, today));
System.out.println("相差的半天数:" + ChronoUnit.HALF_DAYS.between(birthDate, today));
System.out.println("相差的十年数:" + ChronoUnit.DECADES.between(birthDate, today));
System.out.println("相差的世纪(百年)数:" + ChronoUnit.CENTURIES.between(birthDate, today));
System.out.println("相差的千年数:" + ChronoUnit.MILLENNIA.between(birthDate, today));
System.out.println("相差的纪元数:" + ChronoUnit.ERAS.between(birthDate, today));
数组
//数组定义后类型确定,长度固定
//集合类型可以不固定,大小是可变的
//数组可以存储基本类型和引用类型的数据
//集合只能存储引用数据类型的数据
//数组适合做数据个数和类型确定的场景
//集合适合做数据个数不确定,且要做增删元素的场景
//数组 静态初始化
//数据类型[] 数组名 或 数据类型 数组名[]
int[] scores = new int[]{1,2,3,4,5};
int[] ages = {1,2,3,4,5};
//取值 数组名称[索引]
System.out.println(scores[0]);
//赋值
ages[1]= 10;
System.out.println(ages[1]);
//数组 动态初始化数组
//未初始化,会有元素默认值
String[] names = new String[10];
names[0] = "张晶晶";
names[1] = "二师兄";
names[2] = "佩奇";
names[3] = "悟能";
//遍历数组
for (int i = 0; i < names.length; i++) {
System.out.println(names[i]);
}
//猜数据
int[] data = new int[5];
Random random = new Random();
for (int i = 0; i < data.length; i++) {
//随机生成1~20一个数
data[i] = random.nextInt(20)+1;
}
Scanner scanner = new Scanner(System.in);
System.out.println("pls input a num from 1 to 20");
OUT:
while(true){
//随机输入一个1~20的数
int guessData = scanner.nextInt();
//遍历数组与输入数进行比较
for (int i = 0; i < data.length; i++) {
//如果相等,退出死循环
if (guessData == data[i]){
System.out.println("恭喜猜对了");
break OUT;
}
}
//如果不相等,提示输入的不属于数组中某一个
System.out.println("输入的数字不属于数组元素,请重新输入");
}
//如果猜对,遍历元素输出
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + "\t");
}
//随机排名:遍历数组,每次随机一个索引值,让当前元素与该索引位置处的元素进行交换(用temp元素先保存随机索引处元素,将当前索引元素赋值给随机索引元素;然后将temp元素赋值给当前索引元素)
//冒泡排序
第一轮(所有元素)元素1,元素2进行比较,谁大放后边;元素2,元素3进行比较,谁大放后边...
第二轮(除去最后一个元素的所有元素)元素1,元素2进行比较,谁大放后边;元素2,元素3进行比较,谁大放后边...
int[] scores = new int[]{0,2,5,3,1,4};
//排序次数
for (int i = 0; i < scores.length-1; i++) {
//某一个元素与后边的每一项进行排序
for (int j = 0; j < scores.length-i-1; j++) {
if (scores[j] > scores[j+1]){
//将较大值往后排
int temp = scores[j+1];
scores[j+1] = scores[j];
scores[j] = temp;
}
}
}
//遍历
for (int i = 0; i < scores.length; i++) {
System.out.print(scores[i]+"\t");
}
//选择排序
每轮选择当前位置,开始找出后面的较小值(当前位置与后边每个位置进行比较)与该位置交换
Arrays工具类
int[] arr = {10,2,15,30,45,20};
System.out.println(Arrays.toString(arr));//[10, 2, 15, 30, 45, 20]
//排序默认自动对数组元素进行升序排序
Arrays.sort(arr);//[2, 10, 15, 20, 30, 45]
System.out.println(Arrays.toString(arr));
//二分搜索技术(前提数组必须排好序才支持)
int index = Arrays.binarySearch(arr,10);//1
System.out.println(index);
Student[] students = new Student[3];
students[0] = new Student("Jeff",18,180.0);
students[1] = new Student("Lily",20,170.0);
students[2] = new Student("Marry",19,175.5);
//引用类型比较时,实现自定义比较器
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//return o1.getAge()-o2.getAge();
return Double.compare(o1.getWeight(),o2.getWeight());
}
});
//[Student{name='Jeff', age=18, weight=180.0}, Student{name='Marry', age=19, weight=175.5}, Student{name='Lily', age=20, weight=170.0}]
//[Student{name='Lily', age=20, weight=170.0}, Student{name='Marry', age=19, weight=175.5}, Student{name='Jeff', age=18, weight=180.0}]
System.out.println(Arrays.toString(students));
lambda表达式
//1, 正常格式
Integer[] arr= {1,5,3,2,4};
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
System.out.println(Arrays.toString(arr));//[5, 4, 3, 2, 1]
//2, lambda表达式格式
Integer[] arr2= {1,5,3,2,4};
/**
lambda表达式
省略new Comparator<Integer>() {
@Override
public int compare
*/
Arrays.sort(arr2, (Integer o1, Integer o2) -> {
return o2-o1;
});
System.out.println(Arrays.toString(arr2));//[5, 4, 3, 2, 1]
选择排序、二分查找法
//二分查找法
private static int binarySearch(int[] arr, int data) {
//1,定义左边位置和右边位置
int left = 0;
int right = arr.length-1;
//2,开始循环,折半查询
while(left <= right){
//取中间索引
int middleIndex = (left+right)/2;
//3,判断当前中间位置的元素和要找的元素的大小情况
if(data > arr[middleIndex]){
//往右找,左边位置更新为 中间索引+1
left = middleIndex+1;
}else if(data < arr[middleIndex]){
//往左找,右边位置更新为中间索引-1
right = middleIndex-1;
}else if(data == arr[middleIndex]){
return middleIndex;
}
}
return -1;
}
private static void check() {
int[] arr = {2,1,4,3,7,5,6};
//选择排序
//第i项分别与i+1项,i+2项...进行比较,谁大,排后边
for (int i = 0; i < arr.length-1; i++) {
for (int j = i+1; j < arr.length; j++) {
if(arr[i]>arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));//[1, 2, 3, 4, 5, 6, 7]
}
Collection
ArrayList
Collection所有集合的父类
List和Set集合都继承了Collection接口
List系列集合:添加的元素是有序、可重复、有索引
ArrayList底层是基于数组实现的,查询元素快,增删相对慢
数组:因为有索引,所以查询修改快;增删时,需要先数组扩容,再将增删元素之前、之后的元素直接存储,所以增删慢
LinkedList底层基于双链表实现的,查询元素慢,增删首尾元素快
链表:数值域,地址域,地址域存下一个元素地址(单向链表),增删快,查询修改慢
Collection<String> c1 = new ArrayList<>();
c1.add("java");
c1.add("app");
c1.add("java");
System.out.println(c1);//[java, app, java]
//清空集合的元素
//c1.clear();
//System.out.println(c1);//[]
//判断集合是否为空
boolean flag = c1.isEmpty();
System.out.println(flag);//false
//获取集合的大小
System.out.println(c1.size());//3
//判断集合中是否包含某个元素
boolean isContains = c1.contains("java");
System.out.println(isContains);//true
//删除某个元素 如果有多个重复元素默认删除前面的第一个
c1.remove("java");
System.out.println(c1);//[app, java]
//把集合转换成数组
Object[] obj = c1.toArray();
System.out.println("数组元素是: " + Arrays.toString(obj));//数组元素是: [app, java]
//addAll 把cc1集合元素全部加入到c1中
Collection<String> cc1 = new ArrayList<>();
cc1.add("data");
c1.addAll(cc1);
System.out.println(c1);//[app, java, data]
System.out.println(cc1);//[data]
//获取当前集合的迭代器
Iterator<String> it = c1.iterator();
//while循环遍历集合元素
while(it.hasNext()){
String ele = it.next();
System.out.println(ele);
}
//for each遍历集合和数组
for (String str : c1) {
System.out.print(str+" ");//app java data
}
//lambda表达式遍历
c1.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.print(s+" ");//app java data
}
});
c1.forEach((s) -> {
System.out.print(s+" ");//app java data
});
List, ArrayList
ArrayList底层是基于数组实现的,查询元素快,增删相对慢
List<String> list = new ArrayList<>();
list.add("java");
list.add("java");
//在某个索引位置插入元素
list.add(1,"sql");
System.out.println(list);//[java, sql, java]
list.remove("sql");
System.out.println(list.get(0));//java
ArrayList list = new ArrayList();
list.add("Java");
list.add("Java");
list.add(1);
list.add('a');
System.out.println(list);//[Java, Java, 1, a]
//指定位置插入元素
list.add(1,"Oracle");
System.out.println(list);//[Java, Oracle, Java, 1, a]
//JDK1.7开始,泛型后边的类型申明可以不写
//<String>泛型
ArrayList<String> listStr = new ArrayList<>();
listStr.add("mysql");
listStr.add("mysql");
listStr.add("Oracle");
listStr.add("mysql");
listStr.add("sql");
listStr.add("Java");
//类型申明只能是引用类型
ArrayList<Integer> listInt = new ArrayList();
listInt.add(1);
//获取某个索引位置的元素值
System.out.println(listStr.get(1));//Oracle
System.out.println(listStr.size());//4
//遍历
for (int i = 0; i < listStr.size(); i++) {
System.out.println(listStr.get(i));
}
listStr.remove(0);//删除索引为0的元素
System.out.println(listStr);//[mysql, Oracle, mysql, sql, Java]
listStr.remove("mysql");
System.out.println(listStr);//[Oracle, mysql, sql, Java]//删除第一个mysql元素
listStr.set(0,"Developer");
System.out.println(listStr);//[Developer, mysql, sql, Java]
ArrayList<Integer> list = new ArrayList<>();
list.add(79);
list.add(80);
list.add(60);
list.add(90);
list.add(100);
//遍历并删除<80的元素
//需要从后往前遍历,因为从前往后会删除某个元素后,后一个元素占据当前索引位
for (int i = list.size()-1; i >= 0; i--) {
if (list.get(i) < 80)
list.remove(i);
}
System.out.println(list);//[80, 90, 100]
List,LinkedList
LinkedList底层基于双链表实现的,查询元素慢,增删首尾元素快
队列:排队,先进先出
栈:压栈,弹栈,先进后出(LinkedList独有的添加、删除首尾元素可以模拟进栈弹栈)
//LinkedList底层基于双链表实现的,查询元素慢,增删首尾元素快
LinkedList<String> stack = new LinkedList<>();
//入栈 压栈 addFirst(e);
stack.push("第1颗子弹");
stack.push("第2颗子弹");
stack.push("第3颗子弹");
stack.addLast("backup");
System.out.println(stack);//[第3颗子弹, 第2颗子弹, 第1颗子弹, backup]
//出栈 弹栈 removeFirst();
stack.pop();
stack.pop();
System.out.println(stack);//[第1颗子弹, backup]
边遍历,边删除元素
for循环(set集合没有索引,所以不能使用for循环遍历)
Iterator迭代器:继承自Collection,所以list,set都可以拿来遍历
foreach:底层是迭代器
lambda表达式
List<String> lis = new ArrayList<>();
lis.add("java");
lis.add("java");
lis.add("mysql");
lis.add("data");
//for循环(边遍历边删除元素,需要从后往前删除,才不会出现遗漏)
for (int i = lis.size()-1; i >=0; i--) {
if("java".equalsIgnoreCase(lis.get(i))){
lis.remove(i);
}
}
//获取当前集合的迭代器
Iterator<String> its = lis.iterator();
//while循环遍历集合元素
while(its.hasNext()){
String ele = its.next();
if("java".equals(ele)){
//不能在迭代器中,直接操作原集合去删元素,如果需要删除可以用迭代器对象删除
//foreach,lambda表达式不能用来边遍历边删除元素
//lis.remove(ele);//ConcurrentModificationException
its.remove();
}
}
System.out.println(lis);//[mysql, data]
ConcurrentModificationException并发修改异常
1,ListIterator:列表迭代器,将添加元素交给迭代器去做,而非集合
2,for循环添加(set集合没有索引,所以不能使用for循环遍历)
3,使用CopyOnWriteArrayList集合,底层解决并发修改异常,就可以使用普通迭代器去遍历
Set
set集合特点
无序:存取顺序不一致
不重复:可以去除重复
无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素
HashSet:无序、不重复、无索引
LinkedHashSet:有序、不重复、无索引
TreeSet:排序、不重复、无索引
HashSet底层采取哈希表存储的数据
哈希表是一种对于增删改查数据性能都较好的结构
创建一个16位数组,根据哈希值/16求余,计算存入位置,如果当前位置为null,直接存入;如果不为null,equals比较,新老元素运用链表连起来
哈希值:是JDK根据对象的地址,按照某种规则算出来的int类型的数值
Object hashCode()方法获取哈希值(元素对象类重写hashCode(),override的话31*name+age,同一对象hash值相同,不同对象hash值一般不同(重地,通话;儿女,农丰))
JDK8之前,底层使用数组+链表组成
JDK8之后,底层使用数组+链表+红黑树组成
LinkedHashSet底层数据结构依然是哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。有序、不重复、无索引(底层是哈希表+链表,链表保证有序,哈希表保证唯一性)
TreeSet底层是基于红黑树的数据结构实现排序的,增删改查性能都较好
public class Apple implements Comparable<Apple>{
private String name;
private String color;
private double price;
private int weight;
//构造器、get、set、toString方法省略
/**
方式一:类自定义比较规则
o1.compareTo(o2)
*/
@Override
public int compareTo(Apple o) {
// 按照重量进行比较的
return this.weight - o.weight ; // 去重重量重复的元素
// return this.weight - o.weight >= 0 ? 1 : -1; // 保留重量重复的元素
}
}
//TreeSet基本数据结构、String会自动排序
Set<String> set2 = new TreeSet<>();
set2.add("java");
set2.add("Java");
set2.add("ai");
set2.add("基础");
System.out.println(set2);//[Java, ai, java, 基础]
System.out.println("------------------------------");
// 方式二:集合自带比较器对象进行规则定制
Set<Apple> apples = new TreeSet<>(new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
// return o1.getWeight() - o2.getWeight(); // 升序
// return o2.getWeight() - o1.getWeight(); // 降序
// 注意:浮点型建议直接使用Double.compare进行比较 // return Double.compare(o1.getPrice() , o2.getPrice()); // 升序
return Double.compare(o2.getPrice() , o1.getPrice()); // 降序
}
});
//Set<Apple> apples = new TreeSet<>(( o1, o2) -> Double.compare(o2.getPrice() , o1.getPrice()) );
apples.add(new Apple("红富士", "红色", 9.9, 500));
apples.add(new Apple("青苹果", "绿色", 15.9, 300));
apples.add(new Apple("绿苹果", "青色", 29.9, 400));
apples.add(new Apple("黄苹果", "黄色", 9.8, 500));
System.out.println(apples);
可变参数
//底层是数组
//一个形参列表中只能有一个可变参数
//可变参数必须在形参列表最后
public static void sum(int... nums){
//可变参数在方法内部其实就是一个数组
System.out.println(nums.length);
System.out.println(Arrays.toString(nums));
}
Collections工具类
List<String> lists = new ArrayList<>();
Collections.addAll(lists,"java","Java","123");//利用可变参数添加元素
System.out.println(lists);//[java, Java, 123]
Collections.shuffle(lists);//打乱集合顺序
System.out.println(lists);//[Java, java, 123]
Collections.sort(lists);//排序
System.out.println(lists);//[123, Java, java]
List<Apple> apples = new ArrayList<>();
apples.add(new Apple("红富士", "红色", 9.9, 500));
apples.add(new Apple("青苹果", "绿色", 15.9, 300));
apples.add(new Apple("绿苹果", "青色", 29.9, 400));
apples.add(new Apple("黄苹果", "黄色", 9.8, 500));
//方式1:自定义类中实现Comparable接口,重写compareTo方法
//方式2:自定义比较器
Collections.sort(apples, new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return Double.compare(o1.getPrice(), o2.getPrice());
}
});
System.out.println(apples);//[Apple{name='黄苹果', color='黄色', price=9.8, weight=500}, Apple{name='红富士', color='红色', price=9.9, weight=500}, Apple{name='青苹果', color='绿色', price=15.9, weight=300}, Apple{name='绿苹果', color='青色', price=29.9, weight=400}]
public class GameDemo {
/**
点数: "3","4","5","6","7","8","9","10","J","Q","K","A","2"
花色: "♠", "♥", "♣", "♦"
大小王: "👲" , "🃏"
*/
private static List<Card> cards = new ArrayList<>();
static {
String[] sizes = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
String[] colors = {"♠", "♥", "♣", "♦"};
int index = 0;
for (String size : sizes) {
index++;
for (String color : colors) {
Card card = new Card(size,color,index);
cards.add(card);
}
}
Card card1 = new Card("","👲",index++);
Card card2 = new Card("","🃏",index++);
Collections.addAll(cards,card1,card2);
System.out.println(cards);
}
public static void main(String[] args) {
//洗牌
Collections.shuffle(cards);
List<Card> wang = new ArrayList<>();
List<Card> lian = new ArrayList<>();
List<Card> zhang = new ArrayList<>();
//发牌
for (int i = 0; i < cards.size()-3; i++) {
if(i % 3 == 0){
wang.add(cards.get(i));
}else if(i % 3 == 1){
lian.add(cards.get(i));
}else if(i % 3 == 2){
zhang.add(cards.get(i));
}
}
List<Card> dipai = cards.subList(cards.size()-3,cards.size());
//排序
cardsSort(wang);
cardsSort(lian);
cardsSort(zhang);
cardsSort(dipai);
System.out.println(wang);
System.out.println(lian);
System.out.println(zhang);
System.out.println(dipai);
}
private static void cardsSort(List<Card> cards) {
Collections.sort(cards, new Comparator<Card>() {
@Override
public int compare(Card o1, Card o2) {
return o1.getIndex() - o2.getIndex();
}
});
}
}
Map
map包括:key,value。键无序,不重复,无索引。值不做要求
LinkedHashMap键有序,不重复,无索引。值不做要求
TreeMap键排序,不重复,无索引。值不做要求
Map<String,Integer> maps = new HashMap<>();
maps.put("鸿星尔克",2);
maps.put("Java",2);
maps.put("Java",3);//覆盖前面的数据
maps.put(null,null);
System.out.println(maps);//{null=null, Java=3, 鸿星尔克=2}
//maps.clear();//清空集合
System.out.println(maps.isEmpty());//判断是否为空 false
Integer integer = maps.get("鸿星尔克");//根据键获取值
System.out.println(integer);//2
maps.remove("Java");//删除某个元素
System.out.println(maps);//{null=null, 鸿星尔克=2}
System.out.println(maps.containsKey("鸿星尔克"));//true 是否包含某个键
Set<String> sets = maps.keySet();//获取Map集合所有的key
System.out.println(sets);//[null, 鸿星尔克]
Collection<Integer> collection = maps.values();//获取Map集合所有的value
System.out.println(collection);//[null, 2]
System.out.println(maps.size());//集合大小
Map<String,Integer> maps1 = new HashMap<>();
maps1.put("Java1",2);
maps1.put("Java2",2);
Map<String,Integer> maps2 = new HashMap<>();
maps2.put("Java2",2);
maps2.put("Java3",2);
maps1.putAll(maps2);//将maps2复制到maps1中
System.out.println(maps1);//{Java2=2, Java3=2, Java1=2}
System.out.println(maps2);//{Java2=2, Java3=2}
Map遍历
System.out.println("================遍历1:根据key找value==================");
Set<String> keys = maps1.keySet();
for (String key : keys) {
Integer integer1 = maps1.get(key);
System.out.print("key "+ key +" : value "+ integer1 + "\t");//key Java2 : value 2 key Java3 : value 2 key Java1 : value 2
}
System.out.println("\n================遍历2:将map集合转换成set集合==================");
Set<Map.Entry<String,Integer>> entrys = maps1.entrySet();
for (Map.Entry<String, Integer> entry : entrys) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.print(key+" : " + value +"\t");//Java2 : 2 Java3 : 2 Java1 : 2
}
System.out.println("\n================遍历3:lambda==================");
maps1.forEach((key, value) ->{
System.out.print(key+" : " + value +"\t");//Java2 : 2 Java3 : 2 Java1 : 2
});
不可变集合
List<Integer> list = new ArrayList<>();
Collections.addAll(list,1,2,3,4);
//unmodifiableCollection方法生成了不可变集合,由final修饰,所以不能再添减元素
Collection collection = Collections.unmodifiableCollection(list);
collection.add(5);//UnsupportedOperationException
System.out.println(collection);
Stream流
stream流思想核心
1先得到集合或者数组的stream流(就是一根传送带)
2把元素放上去
3然后就用这个stream流简化的API来方便的操作元素
List<String> list = new ArrayList<>();
Collections.addAll(list,"abc","abcd","bcd","ace");
list.stream()
//过滤
.filter(s -> s.startsWith("a"))
//获取元素个数
.filter(s -> s.length()==3)
//去重
.distinct()
//获取前几个元素
.limit(2)
//跳过前几个元素
.skip(2)
//遍历
.forEach(s -> System.out.println(s));
//Collection集合获取流
Collection<String> coll = new ArrayList<>();
Stream s1 = coll.stream();
Map<String, Integer> maps = new HashMap<>();
//键流
Stream<String> keyStream = maps.keySet().stream();
//值流
Stream<Integer> valueStream = maps.values().stream();
//键值对流,拿整体
Stream<Map.Entry<String, Integer>> entryStream = maps.entrySet().stream();
//数组流
String[] names = {};
Stream<String> namesStream = Arrays.stream(names);
Stream<String> namesStream1 = Stream.of(names);
//合并a和b两个流为一个流
Stream.concat(namesStream,namesStream1);
正则表达式
private static void match() {
String rs = "来学习Java,电话020-43422424,或者联系邮箱" +
"abc@test.cn,电话18762832633,0203232323" +
"邮箱test@test.cn,400-100-3233 ,4001003232";
// 需求:从上面的内容中爬取出 电话号码和邮箱。
// 1、定义爬取规则,字符串形式
String regex = "(\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2})|(1[3-9]\\d{9})" +
"|(0\\d{2,6}-?\\d{5,20})|(400-?\\d{3,9}-?\\d{3,9})";
// 2、把这个爬取规则编译成匹配对象。
Pattern pattern = Pattern.compile(regex);
// 3、得到一个内容匹配器对象
Matcher matcher = pattern.matcher(rs);
// 4、开始找了
while (matcher.find()) {
String rs1 = matcher.group();
System.out.println(rs1);
}
}
private static void commen() {
String str = "12345678900";
boolean flag = str.matches("1[3-9]\\d{9}");//\d{9}9位数字
System.out.println(flag);
String email = "12345678900@qq.com";
//boolean isEmail = email.matches("\\w{1,}@[\\w&&[^_]]{1,}[\\.[\\w&&[^_]]{1,}]{1,2}");
boolean isEmail = email.matches("\\w{1,}@[\\w&&[^_]]{1,}(\\.[\\w&&[^_]]{1,}){1,2}");
System.out.println(isEmail);
String str2 = "一ach,二dart,三sabb,";
String[] arrs = str2.split("\\w+,");
for (int i = 0; i < arrs.length; i++) {
System.out.println(arrs[i]);
}
String str3 = str2.replaceAll("\\w+","");//一,二,三,
System.out.println(str3);
}
单例模式
//饿汉单例模式
public class EhanModel {
//静态成员变量初始化构造方法
public static EhanModel instance = new EhanModel();
//私有化构造方法
private EhanModel(){}
}
//懒汉单例模式
public class LanHanModel {
//创建一个静态成员变量存储类的对象,不初始化
private static LanHanModel instance;
//私有化构造方法
private LanHanModel(){}
//获取对象
public static LanHanModel getInstance(){
if (instance == null){
instance = new LanHanModel();
}
return instance;
}
}
模板方法模式
//模板方法模式
//final修饰,因为模板方法不希望被重写
public final void processInfo(String str, String sp){
System.out.println("start");
//将方法中特有部分定义成抽象方法,相同部分定义成模板,提高代码复用性
ArrayList<String> arrayList = split( str, sp);
System.out.println(arrayList);
System.out.println("end");
}
public abstract ArrayList<String> split(String str, String sp);
dynamic proxy动态代理模式
动态代理:
非常灵活,支持任意接口类型的实现类对象做代理,也可以直接为接口本身做代理
可以在不改变方法源代码的情况下,实现方法功能增强
AOP面向切面编程
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtils {
public static <T>T getProxy(T service){
/**
newProxyInstance(ClassLoader loader类加载器,负责加载代理类到内存中使用,
Class<?>[] interfaces获取被代理对象的全部接口,代理要为全部接口的全部方法进行代理,
InvocationHandler h代理的核心处理逻辑)
*/
return (T)Proxy.newProxyInstance(
service.getClass().getClassLoader(),
service.getClass().getInterfaces(),
new InvocationHandler() {
/**
invoke(Object proxy代理对象本身,一般不用,
Method method正在被代理的方法,
Object[] args被处理的方法,应该传入的参数)
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis();
Object object = method.invoke(service,args);
long end = System.currentTimeMillis();
System.out.println(method.getName() + "方法运行时间: " + (end - start) / 1000.0 + " s");
return object;
}
}
);
}
}
public static void main(String[] args) {
//把业务对象直接做成一个代理对象返回,代理对象的类型也是
UserService userService = ProxyUtils.getProxy(new UserServiceImpl());
userService.logon("admin","pwd");
userService.selectUser();
userService.deleteUser();
}
public interface UserService {
String logon(String name, String pwd);
void selectUser();
boolean deleteUser();
}
public class UserServiceImpl implements UserService{
@Override
public String logon(String name, String pwd) {
Thread.sleep(2000l);
return name+" & "+pwd;
}
@Override
public void selectUser() {
Thread.sleep(2000l);
System.out.println("select * from user;");
}
@Override
public boolean deleteUser() {
Thread.sleep(2000l);
return false;
}
}
工厂模式
public class FactoryPattern {
//工厂模式可以封装对象的创建细节,比如:为该对象进行加工和数据注入
public static Computer newComputerInstance(String name) {
return new Computer(name);
}
}
装饰模式
装饰模式:不改变原始类基础上加强基础类功能形成装饰类
抽象类:Inputstream
原始类:FileInoutstream
装饰类:BufferedInputstream
File
import java.io.File;
import java.util.Arrays;
public class FileTest {
public static void main(String[] args) {
/**
* File对象可以定位文件和文件夹
* File封装的对象仅仅是一个路径名,这个路径可以是存在的,也可以是不存在的
*/
//绝对路径
//\n****.log,\r***.log会有歧义,so,"\\"用来转义,表示\
File file =new File("D:\\Developer\\project\\file_io\\temp.txt");
//可以用API"File.separator",有利于不同系统切换
File file1 =new File("D:"+File.separator+"Developer"+File.separator+"project"+File.separator+"file_io"+File.separator+"temp.txt");
//相对路径
//一般定位模块中的文件,相对到工程下
File file2 = new File("abc.log");
File file3 = new File("D:\\Developer\\project\\file_io\\temp1.txt");
File file4 = new File("D:\\Developer\\project\\file_io");
File file5 = new File("D:\\Developer\\project\\file_io\\111\\222\\333");
//[aaa, hello.txt, temp.txt]
System.out.println(Arrays.asList(file4.list()));
//遍历某路径下所有文件和文件夹
File[] listFiles = file4.listFiles();
for (File f : listFiles) {
//D:\Developer\project\file_io\aaa
//D:\Developer\project\file_io\hello.txt
//D:\Developer\project\file_io\temp.txt
System.out.println(f.getAbsolutePath());
}
try {
file3.createNewFile();//创建一个新的空文件
file4.mkdir();//创建一级文件夹
file5.mkdirs();//创建多级文件夹
file3.delete();//删除文件或空文件夹
file3.isDirectory();//判断是否是文件夹
file3.isFile();//判断是否是文件
file3.exists();//文件是否存在
file3.getAbsoluteFile();//返回绝对路径
file3.getPath();//返回路径
file3.getName();//返回文件名称
file3.lastModified();//返回最后修改时间
} catch (IOException e) {
e.printStackTrace();
}
}
}
IO
基础字节流、字符流读写
import java.io.*;
public class IOTest {
public static void main(String[] args) {
InputStream inputStream = null;
OutputStream os = null;
InputStream inputStream2 = null;
OutputStream os2 = null;
try {
System.out.println("===========读取一个字节============");
//文件输入流:创建一个管道,将内存与文件接通
inputStream = new FileInputStream("day01\\src\\abc.log");
//文件输出流:创建一个管道,将内存与管道接通
os = new FileOutputStream("day01\\src\\targe.log");
int temp;
//读取一个字节(每次读取一滴水)
while((temp=inputStream.read()) != -1){
//将一个字节写入文件
os.write(temp);
os.flush();
}
System.out.println("===========读取多个字节============");
inputStream2 = new FileInputStream("day01\\src\\abc.log");
//,true表示不清空目标文件
os2 = new FileOutputStream("day01\\src\\targe2.log",true);
byte[] buffer = new byte[3];
int temp2;
while((temp2=inputStream2.read(buffer)) != -1){
//将一个字节写入文件
os2.write(buffer,0,temp2);
os2.flush();
}
System.out.println("===========读取一个字符============");
Reader reader = new FileReader("day01\\src\\abc.log");
Writer writer = new FileWriter("day01\\src\\targe3.log");
int buff;
while ((buff=reader.read()) != -1){
writer.write(buff);
writer.flush();
}
writer.close();
System.out.println("===========读取一个字符数组============");
Reader reader2 = new FileReader("day01\\src\\abc.log");
Writer writer2 = new FileWriter("day01\\src\\targe4.log");
char[] chars = new char[1024];
while (reader2.read(chars,0,chars.length) != -1){
writer2.write(chars);
writer2.write("\r\n");
writer2.write("abcd");
writer2.flush();
}
writer.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(inputStream);
close(os);
close(inputStream2);
close(os2);
}
}
private static void close(InputStream stream) {
try {
if (stream != null) {
stream.close();
}
} catch(IOException e){
e.printStackTrace();
}
}
private static void close(OutputStream stream) {
try {
if (stream != null) {
stream.close();
}
} catch(IOException e){
e.printStackTrace();
}
}
}
Buffered字节流
try (
InputStream inputStream = new FileInputStream("day01\\src\\abc.log");
//Buffered字节流
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
//true不清空目标文件,将内容追加到目标文件
OutputStream outputStream = new FileOutputStream("day01\\src\\targe.log",true);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
) {
byte[] bytes = new byte[3];
while(bufferedInputStream.read(bytes)!=-1){
bufferedOutputStream.write(bytes,0,bytes.length);
bufferedOutputStream.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
Buffered字符流
//try catch resource 自动释放资源
try (
Reader reader = new FileReader("day01\\src\\abc.log");
//Buffered字符流
BufferedReader bufferedReader = new BufferedReader(reader);
//true不清空目标文件,将内容追加到目标文件
Writer writer = new FileWriter("day01\\src\\targe5.log",true);
BufferedWriter bufferedWriter = new BufferedWriter(writer);
) {
String temp;
while((temp=bufferedReader.readLine()) != null){
bufferedWriter.append(temp);
bufferedWriter.newLine();
bufferedWriter.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
字符转换流
try (
InputStream inputStream = new FileInputStream("H:\\log\\GBK.txt");
//Buffered字节流
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
//字符转换流
InputStreamReader inputStreamReader = new InputStreamReader(bufferedInputStream,"GBK");
//true不清空目标文件,将内容追加到目标文件
OutputStream outputStream = new FileOutputStream("day01\\src\\targe6.log",true);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(bufferedOutputStream,"UTF-8");
) {
char[] chars = new char[3];
while(inputStreamReader.read(chars)!=-1){
outputStreamWriter.write(chars,0,chars.length);
outputStreamWriter.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
对象字节输出流/输入流
序列化/反序列化
Student student = new Student("jack", "pwd");
try (
//对象字节输出流包装字节输出流管道
//序列化对象到文件中
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("day01\\src\\targe7.log"));
){
//调用序列化方法
objectOutputStream.writeObject(student);
//反序列化文件到内存中
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("day01\\src\\targe7.log"));
Student studentSe = (Student)objectInputStream.readObject();
System.out.println(studentSe);//Student{name='jack', pwd='null'}
} catch (Exception e) {
e.printStackTrace();
}
import java.io.Serializable;
//对象类
//对象如果要序列化,必须实现Serializable接口
public class Student implements Serializable {
//序列化版本,每次更新Student类需要更新版本号
private static final long serialVersionUID = 1;
private String name;
private transient String pwd;
}
打印流
try (
//打印流=基础输出流+缓冲流
//打印字节流
PrintStream printStream = new PrintStream("day01\\src\\print1.log");
//有追加需求
PrintStream printStream2 = new PrintStream(new FileOutputStream("day01\\src\\print2.log",true));
//打印字符流
PrintWriter printWriter = new PrintWriter("day01\\src\\print3.log");
){
//打印功能上PrintStream,PrintWriter无区别
printStream.println(97);
printStream.println(true);
printWriter.println("字符串");
//把系统打印流重定向到文件中
System.setOut(printStream2);
System.out.println("================系统打印流重定向到文件====================");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Properties加载资源
Properties properties = new Properties();
try {
//加载熟悉文件到Properties对象中
properties.load(new FileReader("day01\\src\\attrs.properties"));
} catch (IOException e) {
e.printStackTrace();
}
//获取所以的key值
Set<String> set = properties.stringPropertyNames();
System.out.println(set);
if (set.contains("username")){
String name = properties.getProperty("username");
String pwd = properties.getProperty("pwd");
System.out.println(name +" : "+ pwd);
}
CommonIO & NIO
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
try {
IOUtils.copy(new FileInputStream("javatest\\src\\main\\resources\\abc.log"),
new FileOutputStream("javatest\\src\\main\\resources\\abccOPY.log"));
FileUtils.copyFileToDirectory(new File("javatest\\src\\main\\resources\\abc.log"),
new File("H:\\log"));
FileUtils.copyDirectoryToDirectory(new File("H:\\log"),
new File("H:\\log\\copy"));
FileUtils.deleteDirectory(new File(""));
} catch (IOException e) {
e.printStackTrace();
}
多线程
线程创建方式一 继承Thread类
//1,定义一个线程类继承Thread类
public class MyThread extends Thread{
//2,重写run方法
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("子线程执行输出" + i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
//3,new一个线程对象
Thread t1 = new MyThread();
//4,调用start方法启动线程(执行的是run方法)
t1.start();
}
}
线程创建方式二 实现Runnable接口
public class RunnableTest {
public static void main(String[] args) {
//3,创建一个任务对象
Runnable target = new MyRunnable();
//4,把任务对象交给thread处理
Thread thread = new Thread(target);
//5,启动线程
thread.start();
}
}
//1,定义一个线程任务类,实现Runnable接口
class MyRunnable implements Runnable{
//2,重写run方法,定义线程执行的任务
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("子线程执行输出 " + i);
}
}
}
线程创建方式三 实现Callable接口
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableTest {
public static void main(String[] args) {
//3,创建Callable任务对象
Callable callable = new MyCallable();
//4,把Callable任务对象,交给FutureTask对象
//FutureTask对象的作用1:FutureTask实现了Runnable接口,可以交给Thread
//FutureTask对象的作用2:线程执行完可以通过调用get方法得到线程执行结果
FutureTask futureTask = new FutureTask(callable);
//5,交给线程处理
Thread thread = new Thread(futureTask);
//6,启动线程
thread.start();
try {
String result = (String) futureTask.get();
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
//线程创建方式三:
//1,定义一个任务类 实现Callable接口 申明线程任务执行完毕后的结果类型
class MyCallable implements Callable<String>{
//2,重写call方法(任务方法)
@Override
public String call() {
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
return "sum= "+sum;
}
线程安全
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//测试类:构造账户,启动线程
public class ThreadSafe {
public static void main(String[] args) {
Account account1 = new Account("ZH-001", 10000);
Account account2 = new Account("ZH-002", 10000);
new ThreadDemo(account1,"001-01").start();
new ThreadDemo(account1,"001-02").start();
new ThreadDemo(account1,"001-03").start();
}
}
//线程类继承Thread
class ThreadDemo extends Thread{
private Account account;
public ThreadDemo(Account account,String name) {
super(name);
this.account = account;
}
@Override
public void run() {
account.getMoneyFromATM(10000);
}
}
//Account类:操作公共对象
class Account{
private String accName;
private double myMoney;
private final Lock lock = new ReentrantLock();
public Account(String accName, double myMoney) {
this.accName = accName;
this.myMoney = myMoney;
}
//线程不安全
public void getMoneyFromATM(double wantedMoney){
String name = Thread.currentThread().getName();
if (this.myMoney >= wantedMoney){
myMoney-= wantedMoney;
System.out.println(name + "取钱"+wantedMoney+";余额为"+myMoney);
}else{
System.out.println(name + "账户余额不足"+";余额为"+myMoney);
}
}
public void getMoneyFromATM1(double wantedMoney){
String name = Thread.currentThread().getName();
//线程安全
//方法一:同步代码块(对出现问题的核心代码使用进行加锁)
//this指代当前账户对象
//实例对象建议使用this作为锁对象
//静态方法建议使用字节码(类名.class)对象作为锁对象
synchronized (this){
if (this.myMoney >= wantedMoney){
myMoney-= wantedMoney;
System.out.println(name + "取钱"+wantedMoney+";余额为"+myMoney);
}else{
System.out.println(name + "账户余额不足"+";余额为"+myMoney);
}
}
}
//方法二:同步方法
//同步代码块锁范围更小,同步方法锁的范围更大
public synchronized void getMoneyFromATM2(double wantedMoney){
String name = Thread.currentThread().getName();
if (this.myMoney >= wantedMoney){
myMoney-= wantedMoney;
System.out.println(name + "取钱"+wantedMoney+";余额为"+myMoney);
}else{
System.out.println(name + "账户余额不足"+";余额为"+myMoney);
}
}
//方法三:Lock锁
public void getMoneyFromATM3(double wantedMoney){
String name = Thread.currentThread().getName();
lock.lock();
try {
if (this.myMoney >= wantedMoney){
myMoney-= wantedMoney;
System.out.println(name + "取钱"+wantedMoney+";余额为"+myMoney);
}else{
System.out.println(name + "账户余额不足"+";余额为"+myMoney);
}
} finally {
lock.unlock();
}
}
}
线程池
线程池–Runnable方式
import java.util.concurrent.*;
public class ThreadPoolRunnable {
public static void main(String[] args) {
/**
*int corePoolSize主线程个数:正式工,
*int maximumPoolSize最大线程个数:正式工+临时工,
*long keepAliveTime临时工工作完多久释放,
*TimeUnit unit时间单位,
*BlockingQueue<Runnable> workQueue工作队列:等待区线程最大个数,也就是最多几个任务在等待被线程执行,
*ThreadFactory threadFactory线程工厂hr,
*RejectedExecutionHandler handler拒绝策略
*/
ExecutorService pool = new ThreadPoolExecutor(3,5,5, TimeUnit.SECONDS
,new ArrayBlockingQueue<>(6)
,Executors.defaultThreadFactory()
,new ThreadPoolExecutor.AbortPolicy());
for (int i = 1; i <= 11; i++) {
pool.execute(new MyRunnable());
}
//rejected from java.util.concurrent.ThreadPoolExecutor@135fbaa4[Running, pool size = 5, active threads = 5, queued tasks = 6, completed tasks = 0]
//at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
//最大线程容量5+最大等待线程数量6,so,当线程数量>11时,就会报出来
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行");
}
}
线程池–Callable方式
import java.util.concurrent.*;
public class ThreadPoolCallable {
public static void main(String[] args) {
/**
*int corePoolSize,
*int maximumPoolSize,
*long keepAliveTime,
*TimeUnit unit,
*BlockingQueue<Runnable> workQueue,
*ThreadFactory threadFactory,
*RejectedExecutionHandler handler
*/
ExecutorService pool = new ThreadPoolExecutor(3,5,5, TimeUnit.SECONDS
,new ArrayBlockingQueue<>(6)
,Executors.defaultThreadFactory()
,new ThreadPoolExecutor.AbortPolicy());
//线程池去执行线程,返回Future对象
Future<String> future1 = pool.submit(new MyCallable(5));
Future<String> future2 = pool.submit(new MyCallable(6));
Future<String> future3 = pool.submit(new MyCallable(7));
try {
//返回线程返回值
System.out.println(future1.get());
System.out.println(future2.get());
System.out.println(future3.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable<String> {
private int n;
public MyCallable(int n) {
this.n = n;
}
@Override
public String call() {
int sum = 0;
for (int i = 0; i < n; i++) {
sum+=i;
}
return Thread.currentThread().getName()+",0~"+n+";sum = "+sum;
}
}
线程池–Executors去创建线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FixedThread {
public static void main(String[] args) {
/**
* Executors去创建线程池可能出现系统风险
* 大量任务需要等待少量线程去处理,导致内存溢出
* 大量线程被创建,导致内存溢出
*/
ExecutorService pool = Executors.newFixedThreadPool(3);
/**
* pool-1-thread-1正在执行
* pool-1-thread-2正在执行
* pool-1-thread-1正在执行
* pool-1-thread-3正在执行
*/
pool.execute(new MyRunnable());
pool.execute(new MyRunnable());
pool.execute(new MyRunnable());
pool.execute(new MyRunnable());//3个线程(正式员工)来执行4个线程任务
}
}
定时器
方式一:Timer不推荐
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
Timer timer = new Timer();//定时器本身就是一个单线程
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行");
try {
//问题一:Timer是单线程,处理多个任务按照顺序执行,存在延时与设置定时器的时间有出入
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},2000,3000);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行");
//问题二:某个任务异常使Timer线程挂掉,从而影响后续任务执行
System.out.println(10 / 0);
}
},2000,3000);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行");
}
},2000,3000);
}
}
方式二:Executors.newScheduledThreadPool
Timer的升级版
import java.util.Date;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledTask {
public static void main(String[] args) {
//Timer upgrade,解决Timer单个线程处理时,因个别任务执行异常,导致线程任务异常的情况
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
/**
* Runnable command,线程任务
*long initialDelay,多久开始
*long period,每隔多久执行一次
*TimeUnit unit);时间单位
*/
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在执行1;"+new Date());
}
},1,2,TimeUnit.SECONDS);
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
//某个线程执行异常不会影响其他线程
System.out.println(10 / 0);
System.out.println(Thread.currentThread().getName()+"正在执行2;"+new Date());
}
},1,2,TimeUnit.SECONDS);
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行3;"+new Date());
}
},1,2,TimeUnit.SECONDS);
}
}
junit单元测试
//原始类
public class Logon {
public boolean equals(String str) {
return "admin".equals(str);
}
public void sys(String str) {
System.out.println(str);
}
}
//单元测试类
public class TestLogon {
//鼠标指向测试方法内部右击只测一个方法,指向类右击可以测整个类的方法
@Test
public void testEquals(){
Logon logon = new Logon();
boolean flag = logon.equals("admin");
//进行正确性预测 断言
Assert.assertEquals("function issue", true, flag);
}
@Test
public void testSys(){
Logon logon = new Logon();
logon.sys("str");
}
//修饰实例方法
@Before
public void before(){
System.out.println("每个测试方法前执行一次,用于初始化资源");
}
@After
public void after(){
System.out.println("每个测试方法后执行一次,用于释放资源");
}
//修饰静态方法
@BeforeClass
public void beforeClass(){
System.out.println("每个测试类前执行一次,用于初始化资源");
}
@AfterClass
public void afterClass(){
System.out.println("每个测试类后执行一次,用于释放资源");
}
}
reflect反射
获取类对象
获取构造器
获取成员变量
获取成员方法
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
try {
//获取类对象
//com\benjamin\reflect\Test.java
Class clazz1 = Class.forName("com.benjamin.reflect.Student");
Class clazz2 = Student.class;
Student student = new Student();
Class clazz3 = student.getClass();
System.out.println(clazz1);
System.out.println(clazz2);
System.out.println(clazz3);
//获取public构造器
Constructor[] constructors = clazz1.getConstructors();
//获取所有构造器
Constructor[] allConstructors = clazz1.getDeclaredConstructors();
//获取某一个构造器
Constructor consOne = clazz1.getDeclaredConstructor(String.class,int.class);
consOne.setAccessible(true);
//构造对象
Student stuInstance = (Student)consOne.newInstance("admin",123456);
System.out.println(stuInstance);//Student{name='admin', pwd=123456}
for (Constructor constructor:constructors) {
System.out.println(constructor.getName());
System.out.println(constructor.getParameterCount());
}
//获取所有的成员变量
Field[] fields = clazz1.getDeclaredFields();
//获取public成员变量
Field[] pubFields = clazz1.getFields();
Field fieldName = clazz1.getDeclaredField("name");
fieldName.setAccessible(true);//对私有化属性进行强制赋值
fieldName.set(student,"admin");//成员变量进行赋值
System.out.println(student);//Student{name='admin', pwd=0}
//获取成员方法
Method[] methods = clazz1.getDeclaredMethods();
Method method = clazz1.getDeclaredMethod("str",int.class);
method.setAccessible(true);
//方法执行
method.invoke(student,123);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Student {
private String name;
private int pwd;
public Student(){}
private Student(String name, int pwd) {
this.name = name;
this.pwd = pwd;
}
private void str(int pwd){
this.pwd = pwd;
System.out.println("pwd : "+pwd);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", pwd=" + pwd +
'}';
}
}
1,以下requestbody中的keyname是由查询字典(queryDictionaryData?dicttype=page_repair_task)拿到的
2,查询时,可以根据查询的是taskno或taskname动态添加查询条件
http://localhost:8080/maintenancetask/query
{"keyname":"taskname","keyvalue":"2023050511112327_HHHT0104503_FO01","metrono":"","doorno":"","clickList":["H"],"areaid":22,"countryid":3,"tasktype":0,"pageNumber":1,"pageSize":10}
3,利用反射拿到表中字段属性名,从而动态生成sql查询条件
//关键字筛选条件
Field[] fields = ViewMaintainTask.class.getDeclaredFields();
Set<String> names = new HashSet<>();
for (Field field1 : fields) {
names.add(field1.getName());
}
if (maintenanceTaskSearchVO.getKeyname() != null && maintenanceTaskSearchVO.getKeyvalue() != null && maintenanceTaskSearchVO.getKeyvalue().trim() != "") {
if (names.contains(maintenanceTaskSearchVO.getKeyname())) {
criteria.andLike(maintenanceTaskSearchVO.getKeyname(), "%" + maintenanceTaskSearchVO.getKeyvalue() + "%");
}
}
1,Keyname的值,由查询字典拿到,sys_dict_data表中定义了dicttype=page_repair_task的taskno和taskname
http://localhost:8080/dictionary/queryDictionaryData?dicttype=page_repair_task
{
"returnCode": 0,
"returnMessage": "调用成功",
"data": [
{
"dictDataId": 49,
"dictLabel": "任务单号",
"dictValue": "taskno",
"icon": null
},
{
"dictDataId": 153,
"dictLabel": "任务名称",
"dictValue": "taskname",
"icon": null
}
]
}
annotation注解
自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//元注解 注解的注解
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE})//自定义注解标记范围
@Retention(RetentionPolicy.RUNTIME)//注解生命周期 RUNTIME一直活着
//自定义注解
public @interface Book {
String value();
double prica() default 100;
String[] authers();
}
自定义注解运用
@Book(value = "《JAVA learning》",prica = 99, authers = {"james"})
public class BookTest {
@Book(value = "《Nexus》",prica = 199, authers = {"leunx"})
public void test(){
}
}
自定义注解解析
Class clazz = BookTest.class;
//判断类上是否有Book这个注解
if(clazz.isAnnotationPresent(Book.class)){
Book book = (Book)clazz.getDeclaredAnnotation(Book.class);
//《JAVA learning》 & 99.0 & [james]
System.out.println(book.value() +" & "+ book.prica()+" & "+ Arrays.toString(book.authers()));
}
//判断方法上是否有Book这个注解
Method method = clazz.getDeclaredMethod("test");
if(method.isAnnotationPresent(Book.class)){
Book book = (Book)method.getDeclaredAnnotation(Book.class);
//《Nexus》 & 199.0 & [leunx]
System.out.println(book.value() +" & "+ book.prica()+" & "+Arrays.toString(book.authers()));
}
dom4j
pom dependency
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.1</version>
</dependency>
@Test
public void parseContacts()throws Exception {
//1,创建一个dom4j解析器对象,代表了整个dom4j框架
SAXReader saxReader = new SAXReader();
//getResourceAsStream中"/是直接去src下寻找的文件//com/test/java/learning/dom4j/contacts.xml
//D:\Developer\project\NewProject\javatest\src\main\resources\xml\contacts.xml
InputStream inputStream = new FileInputStream("D:\\Developer\\project\\NewProject\\javatest\\src\\main\\resources\\xml\\contacts.xml");
//InputStream inputStream=Dom4iDemo.class.aetResourceAsStream("/main.java.com.test.java.learnina.dom4i.contacts.xml"):
//2,把xml文件加载到内存中成为一个Document文档对象
Document document = saxReader.read(inputStream);
//3,获取根元素对象
Element root = document.getRootElement();
List<Element> eleContact = root.elements("contact");
List<Contact> list = new ArrayList<>();
for (Element element : eleContact) {
Contact contact = new Contact();//get son element value
contact.setName(element.elementTextTrim("name"));
//元素的子开素的值
contact.setEmail(element.elementTextTrim("email"));
contact.setGendar(element.elementTextTrim("gendar").charAt(0));
//get attribute value
contact.setId(Integer.valueOf(element.attributeValue("id")));
contact.setVip(Boolean.valueOf(element.attributeValue("vip")));
list.add(contact);
}
System.out.println(list);
}
contacts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<contacts>
<contact id="001" vip="true">
<name>张三</name>
<gendar>男</gendar>
<email>zhangsan.hsbc.com</email>
</contact>
<contact id="002" vip="false">
<name>乃呀</name>
<gendar>女</gendar>
<email>naiya.hsbc.com</email>
</contact>
<blacklist>
<contact>
<id>
<name>孬蛋</name>
</id>
</contact>
</blacklist>
</contacts>
Xpath xml检索
@Test
public void searchNode() throws Exception {
//1,创建一个dom4j解析器对象,代表了整个dom4j框架
SAXReader saxReader = new SAXReader();
InputStream inputStream = new FileInputStream("src\\main\\resources\\xml\\contacts.xml");
//InputStream inputStream = Dom4jDemo.class.getResourceAsStream("/main.java.com.test.java.learning.dom4j.contacts.xml");
// 2,把xml文件加载到内存中成为一个Document文档对象
Document document = saxReader.read(inputStream);
//3,检索元素
/**
/指检索的文件 "/contacts/contact/name"
"//contact/name"指所有contact下子元素name
"//contact//name"指所有contact下子子孙孙元素name
*/
List<Node> nodes = document.selectNodes("//contact//name");
for (Node node : nodes) {
Element element = (Element) node;
System.out.println(element.getTextTrim());//元素的值
}
//4,检索属性
/**
//@id 查询属性为id的属性
//name[@id]查询name元素包含id属性
//name[eid=888]查询name元素包含id属性=888
*/
List<Node> nodesAttr = document.selectNodes("//@id");
for (Node node : nodesAttr) {
Attribute attr = (Attribute) node;
System.out.println(attr.getValue());//属性的值
}
}
net网络编程
概念
net key:
ip:每台主机的网络地址
计算机call域名www.baidu.com<--②解析域名为ip,返回给计算机①-->dns服务器(域名解析器,在本地电脑上)
--③计算机再访问-->baidu服务器
if计算机第一次访问某个域名,本地dns服务器没有记录(域名ip)-->请求发至电信运营商,return此ip
192.168开头的常见的局域网地址,范围为192.168.0.0~192168255.255,专门为组织机构内部使用
ipconfig查看本地ip地址
ping 某IPAddress:检查网络是否连通
本机 IP127.0.0.1或者localhost
port:主机上的应用编号
端口号:标记正在计算机设备上运行的进程(程序).被规定为一个16位的二进制,范围是0~65535
周知端口 0~1023,被预先定义的知名应用占用(HTTP占用80,FTP占用21)
注册端口 1024~49151,分配给用户进程或某些应用程序(Tomcat8080,MySQL3306)
动态端口 49152~65535,之所以称为动态端口,是因为它一般不固定分配某种进程,而是动态分配
协议:
连接和通信数据的规则被称为网络通信协议
TCP(Transmission Control Protocol)传输控制协议
TCP三次握手确立连接
客户端--发连接请求,确认客户端发消息ok-->服务器端
客户端<--返回响应,确认服务端收消息,回复消息ok
服务器端--发请求,确认客户端收消息ok-->服务器端
TCP四次挥手断开连接
客户端 --pls cancel contact--> 服务器端
客户端 <--waiting,processing残余msg-- 服务器端
客户端 <--really cancel?-- 服务器端
客户端 --yes pls close contact--> 服务器端
UDP(User Datagram Protocol)用户数据报协议
面向无连接,不可堂传输的通信协议
广播,语音通话,视频会话
UDP广播
使用广播地址255.255.255.255 port 9999接收端只要匹配端口9999成功就可以收到消息
UDP组播
使用组播地址224.0.0.0-239.255.255.255,指定port
接收端使用DatagromSocket的子类MulricastSocket绑定组播ip,加入该组播group
//1,获取本机ip
InetAddress addressl = InetAddress.getLocalHost();
System.out.println(addressl.getHostName());//A156DOL62VAYN6U
System.out.println(addressl.getHostAddress());//133.7.98.208本机局域网地址
//判断是否连通,5s内是否能连通
System.out.println(addressl.isReachable( 5000));
//2.获取域名ip对象
InetAddress address2 = InetAddress.getByName("www.baidu.com");
System.out.println(address2.getHostName());
System.out.println(address2.getHostAddress());//36.152.44.96
UDP(User Datagram Protocol)用户数据报协议
客户端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws Exception {
System.out.println("=====客户端启动======");
// 1、创建发送端对象:发送端自带默认的端口号(人)
DatagramSocket socket = new DatagramSocket(7777);
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请说:");
String msg = sc.nextLine();
if("exit".equals(msg)){
System.out.println("离线成功!");
socket.close();
break;
}
// 2、创建一个数据包对象封装数据(韭菜盘子)
byte[] buffer = msg.getBytes();
DatagramPacket packet = new DatagramPacket( buffer, buffer.length,
InetAddress.getLocalHost() , 8888);
// 3、发送数据出去
socket.send(packet);
}
}
}
服务器端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("=====服务端启动======");
// 1、创建接收端对象:注册端口(人)
DatagramSocket socket = new DatagramSocket(8888);
// 2、创建一个数据包对象接收数据(韭菜盘子)
byte[] buffer = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (true) {
// 3、等待接收数据。
socket.receive(packet);
// 4、取出数据即可
// 读取多少倒出多少
int len = packet.getLength();
String rs = new String(buffer,0, len);
System.out.println("收到了来自:" + packet.getAddress() +", 对方端口是" + packet.getPort() +"的消息:" + rs);
}
}
}
TCP(Transmission Control Protocol)传输控制协议
多client --> 单server(弹幕)
客户端
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws Exception{
System.out.println("====客户端启动===");
// 1、创建Socket通信管道请求有服务端的连接
// public Socket(String host, int port)
// 参数一:服务端的IP地址c
// 参数二:服务端的端口
Socket socket = new Socket("127.0.0.1", 7777);
// 2、从socket通信管道中得到一个字节输出流 负责发送数据
OutputStream os = socket.getOutputStream();
// 3、把低级的字节流包装成打印流
PrintStream ps = new PrintStream(os);
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("pls write ");
String msg = sc.nextLine();
// 4、发送消息
ps.println(msg);
ps.flush();
}
}
}
服务器端
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;
public class Server {
private static final ExecutorService pool = new ThreadPoolExecutor(1,5,5, TimeUnit.SECONDS
,new ArrayBlockingQueue<>(1)
,Executors.defaultThreadFactory()
,new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) {
try {
System.out.println("===服务端启动成功===");
// 1、注册端口
ServerSocket serverSocket = new ServerSocket(7777);
// a.定义一个死循环由主线程负责不断的接收客户端的Socket管道连接。
while (true) {
// 2、每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取消息
Socket socket = serverSocket.accept();
System.out.println(socket.getRemoteSocketAddress()+ " is online!");
// 3、开始创建独立线程处理socket
pool.execute(new ServerReaderRunnable(socket));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
线程类
public class ServerReaderRunnable implements Runnable{
private Socket socket;
public ServerReaderRunnable(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
// 3、从socket通信管道中得到一个字节输入流
InputStream is = socket.getInputStream();
// 4、把字节输入流包装成缓冲字符输入流进行消息的接收
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// 5、按照行读取消息
String msg;
while ((msg = br.readLine()) != null){
System.out.println(Thread.currentThread().getName()+" "+socket.getRemoteSocketAddress() + "说了:: " + msg);
}
} catch (Exception e) {
System.out.println(socket.getRemoteSocketAddress() + "is offline");
}
}
}
多client --> 单server --> 多client(实时聊天)
客户端
public class Client {
public static void main(String[] args) throws Exception{
System.out.println("====客户端启动===");
// 1、创建Socket通信管道请求有服务端的连接
// public Socket(String host, int port)
// 参数一:服务端的IP地址
// 参数二:服务端的端口
Socket socket = new Socket("127.0.0.1", 7777);
//读取别人发的消息
new ReaderThread(socket).start();
// 2、从socket通信管道中得到一个字节输出流 负责发送数据
OutputStream os = socket.getOutputStream();
// 3、把低级的字节流包装成打印流
PrintStream ps = new PrintStream(os);
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("pls write");
String msg = sc.nextLine();
// 4、发送消息
ps.println(msg);
ps.flush();
}
}
}
服务器端
public class Server {
/**
多个clients --> server --> 多个clients
*/
public static final List<Socket> lists = new ArrayList<>();
public static void main(String[] args) {
try {
System.out.println("===服务端启动成功===");
// 1、注册端口
ServerSocket serverSocket = new ServerSocket(7777);
// a.定义一个死循环由主线程负责不断的接收客户端的Socket管道连接。
while (true) {
// 2、每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取消息
Socket socket = serverSocket.accept();
//记录online client
lists.add(socket);
System.out.println(socket.getRemoteSocketAddress()+ " is online");
// 3、开始创建独立线程处理socket
new ReaderThread(socket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
server读取clients发送的消息和clients读取server转发的消息时的子线程
public class ReaderThread extends Thread{
private Socket socket;
public ReaderThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
// 3、从socket通信管道中得到一个字节输入流
InputStream is = socket.getInputStream();
// 4、把字节输入流包装成缓冲字符输入流进行消息的接收
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// 5、按照行读取消息
String msg;
while ((msg = br.readLine()) != null){
System.out.println(Thread.currentThread().getName()+" "+socket.getRemoteSocketAddress() + " say==> " + msg);
pushMsgToClients(msg);
}
} catch (Exception e) {
//when client is killed, remove it from list
Server.lists.remove(socket);
System.out.println(Thread.currentThread().getName()+" "+socket.getRemoteSocketAddress() + " is killed");
}
}
private void pushMsgToClients(String msg) throws Exception{
for (Socket socket : Server.lists) {
OutputStream outputStream = socket.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
printStream.println(Thread.currentThread().getName()+socket.getRemoteSocketAddress()+" say --> "+msg);
printStream.flush();
}
}
}
ip和Long进行转换
public class IpConverter {
/**
* 把字符串IP转换成LONG
* Long.parseLong(ip[0]) << 24 左位移24位
* @param ipStr 字符串IP
* @return IP对应的LONG值
*/
public static long ip2Long(String ipStr) {
String[] ip = ipStr.split("\\.");
return (Long.parseLong(ip[0]) << 24) + (Long.parseLong(ip[1]) << 16) + (Long.parseLong(ip[2]) << 8) + Long.parseLong(ip[3]);
}
/**
* 0xFF 255 11111111 (ipLong >>> 16) & 0xFF取后八位
* 任何数与它做与运算(&)就是去取这个数的二进制的最后八位
* @param ipLong
* @return
*/
public static String long2Ip(long ipLong) {
return (ipLong >>> 24) + "." +
((ipLong >>> 16) & 0xFF) + "." +
((ipLong >>> 8) & 0xFF) + "." +
(ipLong & 0xFF);
}
}
获取IP及归属地
public class IpUtils {
/**
* X-Forwarded-For:一个 HTTP 扩展头部,主要是为了让 Web 服务器获取访问用户的真实 IP 地址。每个 IP 地址,每个值通过逗号+空格分开,最左边是最原始客户端的 IP 地址,中间如果有多层代理,每⼀层代理会将连接它的客户端 IP 追加在 X-Forwarded-For 右边。
* X-Real-IP:一般只记录真实发出请求的客户端IP
* Proxy-Client-IP:这个一般是经过 Apache http 服务器的请求才会有,用 Apache http 做代理时一般会加上 Proxy-Client-IP 请求头
* WL-Proxy-Client-IP:也是通过 Apache http 服务器,在 weblogic 插件加上的头。
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("http_client_ip");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip != null && ip.indexOf(",") != -1) {
ip = ip.substring(ip.lastIndexOf(",") + 1, ip.length()).trim();
}
System.out.println("出现访问IP:" + ip);
return ip;
}
/**
* 2.通过调用接口的方式获取IP
*/
public static String getIp() {
try {
URL realUrl = new URL("http://whois.pconline.com.cn/ipJson.jsp");
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
conn.setRequestMethod("GET");
conn.setUseCaches(false);
conn.setReadTimeout(6000);
conn.setConnectTimeout(6000);
conn.setInstanceFollowRedirects(false);
int code = conn.getResponseCode();
StringBuilder sb = new StringBuilder();
String ip = "";
if (code == 200) {
InputStream in = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
ip = sb.substring(sb.indexOf("ip") + 5, sb.indexOf("pro") - 3);
}
return ip;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 3.通过调用接口根据ip获取归属地
*/
public static String getAddress(String ip) {
try {
URL realUrl = new URL("http://whois.pconline.com.cn/ipJson.jsp?ip=" + ip + "&json=true");
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
conn.setRequestMethod("GET");
conn.setUseCaches(false);
conn.setReadTimeout(6000);
conn.setConnectTimeout(6000);
conn.setInstanceFollowRedirects(false);
int code = conn.getResponseCode();
StringBuilder sb = new StringBuilder();
String ipaddr = "";
if (code == 200) {
InputStream in = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in,"GBK"));
String line;
while ((line = reader.readLine()) != null) {
//String decode = URLDecoder.decode(line,"GBK");
sb.append(line);
}
ipaddr = ip + "=" + sb.substring(sb.indexOf("addr") + 7, sb.indexOf("regionNames") - 3);
}
return ipaddr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
建造者模式 .builder() 用来构建对象
@Builder
public class ProjectInfoVO {}
//构建ProjectInfoVO
ProjectInfoVO temp = ProjectInfoVO.builder()
.id(doorProjectInfo.getId())
.createTime(doorProjectInfo.getCreatetime())
.partnername(partner != null ? partner.getPartnername() : "")
.doorcategory(categoryname)
.projectname(doorProjectInfo.getProjectname())
.projectprobleminfo(stringBuilder.toString())
.dealstatus(doorProjectInfo.getDealstatus())
.build();
list.add(temp);
BeanUtils.copyProperties( )
java Beanutils.copyProperties( )用法详解
SurfChnMulDayInfoVO surfChnMulDayInfoVO = new SurfChnMulDayInfoVO();
surfChnMulDayInfoVO.setCalc("ca");
surfChnMulDayInfoVO.setId(1);
SurfChnMulDayInfoVO surfChnMulDayInfoVO2 = new SurfChnMulDayInfoVO();
// 赋值
//BeanUtils.copyProperties("要转换的类", "转换后的类");
BeanUtils.copyProperties(surfChnMulDayInfoVO,surfChnMulDayInfoVO2);
将一个自定义对象的值赋予另一个自定义对象
import org.apache.commons.beanutils.BeanUtils;
List<SurfChnMulMinRetData.SurfChnMulMinRetDataItem> ds = surfChnMulMinRetData.getDs();
ds.forEach(
item -> {
if (!(item.getQPre1h() == 0 || item.getQPre1h() == 3 || item.getQPre1h() == 4)) {
item.setPre1h(0.0);
}
StationLiveHistory stationLiveHistory = new StationLiveHistory();
try {
// 赋值
//BeanUtils.copyProperties("赋值后的对象", "赋值前的对象");
BeanUtils.copyProperties(stationLiveHistory, item);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
stationLiveHistoryList.add(stationLiveHistory);
}
);
Cannot resolve symbol
Cannot resolve symbol 解决方案汇总(6种解决方案)
excel导出导入
Java实现Excel导入和导出
其他代码见以上文档
import com.meteorological.pojo.excel.ExcelVO;
import com.meteorological.utils.excel.ExcelUtils2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Service
public class ExportExcelService implements IExportExcelService{
@Override
public void export(HttpServletResponse response, ExcelVO vo) {
if(vo!=null && vo.getData()!=null && vo.getData().size()>0){
String excelName = vo.getTitle();
if(StringUtils.isEmpty(excelName)){
excelName = "陕西省";
}
List<List<Object>> lists = vo.getData();
List<List<Object>> newLists = new ArrayList<>();
newLists.addAll(lists);
if(lists.size()>2){
for (int i = lists.size()-1; i > 1; i--) {
List<Object> objectsLastRow = lists.get(i-1);
List<Object> objectsThisRow = lists.get(i);
if(Objects.equals(objectsLastRow.get(0),objectsThisRow.get(0))){
//objectsThisRow.remove(0);
objectsThisRow.set(0,ExcelUtils2.ROW_MERGE);
}
newLists.set(i,objectsThisRow);
}
}
//导出数据
ExcelUtils2.export(response,excelName,newLists);
}
}
}