Java基础

常见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()的使用

使用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进行转换

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及归属地

获取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() 用来构建对象

java中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);
        }

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值