Java 开发常用工具方法

714人浏览 / 0人评论

BigDecimal与Double的区别和使用场景

https://blog.csdn.net/qq_43842093/article/details/135038362

Double的问题

在计算时会出现不精确的问题

public static void main(String[] args) {
    System.out.println(12.3 + 45.6); // 57.900000000000006
    System.out.println(12.3 / 100); // 0.12300000000000001
}

小数部分无法使用二进制准确的表示

等于判断在使用时需要注意

public static void main(String[] args) {
    double a = 2.111111111111111111111111112;
    double b = 2.111111111111111111111111113;
    // duoble超过15位以后就会不对了
    System.out.println(a == b); // true
}

BigDecimal的问题

使用除法时除不尽会报 ArithmeticException 异常

public static void main(String[] args) {
    // 报异常:Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
    System.out.println(BigDecimal.valueOf(121).divide(BigDecimal.valueOf(3)));
}


public static void main(String[] args) {
    // 需要指定精度和舍入方式,当除不尽时也不会报异常 
    // 运行结果为 40.33
    System.out.println(BigDecimal.valueOf(121).divide(BigDecimal.valueOf(3), 2, RoundingMode.HALF_UP)); 
}

new BigDecimal(double)结果或许预料不到

public static void main(String[] args) {
    BigDecimal a = new BigDecimal(12.3);
    BigDecimal b = BigDecimal.valueOf(12.3);
    // Double的小数位其实无法被精确表示,所以传入的.3被精度扩展之后精度丢失,展示出来的并不是精确的.3
    // 结果为12.300000000000000710542735760100185871124267578125
    System.out.println(a);
    // 从底层代码可以看出来,BigDecimal.valueOf 会先转换为字符串之后再调用new BigDecimal,不会造成精度丢失
    // 结果为12.3
    System.out.println(b);
}

所以一般情况下会使用BigDecimal.valueOf()而不是new BigDecimal()。

另:BigDecimal.valueOf() 是静态工厂类,永远优先于构造函数。

BigDecimal是不可变类

不可变类代表着,任何针对BigDecimal的修改都将产生新对象。所以每次对BigDecimal的修改都要重新指向一个新的对象。

public static void main(String[] args) {
    BigDecimal a = BigDecimal.valueOf(12.3);
    a.add(BigDecimal.valueOf(2.1));
    System.out.println(a); // 12.3,值未修改

    BigDecimal b = BigDecimal.valueOf(12.3);
    // 重新赋值给新对象
    BigDecimal c = b.add(BigDecimal.valueOf(2.1));
    System.out.println(c); // 14.4
}

BigDecimal大小的比较都需要使用compareTo,如果需要返回更大的数或更小的数可以使用max、min。还要注意在BigDecimal中慎用equals。

public static void main(String[] args) {
    BigDecimal a = BigDecimal.valueOf(12.3);
    BigDecimal b = BigDecimal.valueOf(12.32);
    System.out.println(a.compareTo(b)); // -1
    System.out.println(b.compareTo(a)); //1
    System.out.println(a.max(b)); // 12.32
    System.out.println(a.min(b)); // 12.3
    System.out.println(b.max(a)); // 12.32
    System.out.println(b.min(a)); // 12.3
    System.out.println(BigDecimal.valueOf(1).equals(BigDecimal.valueOf(1.0))); //false
}

BigDecimal重写了equals方法,在equals方法里比较了小数位数,在方法注释上也有说明,所以 BigDecimal.valueOf(1).equals(BigDecimal.valueOf(1.0)) 为什么结果为false就可以理解了。

静态map初始化并赋值问题

代码评审——静态map初始化并赋值问题_map静态代码块改造-CSDN博客

// 方法一
public static final Map<String, String> staticMap = createMap();
private static Map<String, String> createMap() {
	Map<String, String> result = new HashMap<>();
	result.put("1", "one");
	result.put("2", "two");
	return Collections.unmodifiableMap(result);
}

// 方法二
public static final Map<String, String> staticMap;
static {
	staticMap = new HashMap<String, String>();
	staticMap.put("1", "one");
	staticMap.put("2", "two");
	staticMap.put("3", "three");
	staticMap.put("4", "four");
	staticMap.put("5", "five");
}

// 方法三:使用Map.ofEntries初始化(仅支持Java 9+)其中,Map.of()仅能初始化10以内的数据
private static final Map<String,String> staticMap = Map.ofEntries(
	entry("1", "one"),
	entry("2", "two"),
	entry("3", "three"),
	entry("4", "four"),
	entry("5", "five")
);

简单文件读写

// 读取数据
Path path = Paths.get("D:/aa.txt");
byte[] data = Files.readAllBytes(path);
String result = new String(data, StandardCharsets.UTF_8);

// 写入到文件
FileWriter writer = new FileWriter("D:/aa.txt");
writer.write("hello world");
writer.close();

CollectionUtils

import org.apache.commons.collections4.CollectionUtils;

// 判断集合是否为空
CollectionUtils.isEmpty(list)
CollectionUtils.isNotEmpty(list)
// 不要用 list.isEmpty(),因为如果 list = null,会报空指针异常。
// 控制层接口中如果规定返回的数据是 List<实体类> 的型式,而结果为空的话,可以使用:
return Lists.newArrayList();

// 初始化集合
List<Object> list = Lists.newArrayList();

StringUtils

 // lang包可视作废弃,不再使用
import org.apache.commons.lang3.StringUtils;

// 常用方法
isEmpty(String str) //是否为空,空格字符为false
isNotEmpty(String str) //是否为非空,空格字符为true
isBlank(String str) //是否为空,空格字符为true
isNotBlank(String str) //是否为非空,空格字符为false
trim(String str) //去除字符串两端的控制符,空字符串、null 返回 null
trimToEmpty(String str) //去除字符串两端的控制符,空字符串、null 返回""
stripToNull(String str) //去除字符串两端的空白符,空字符串、null 返回null
stripToEmpty(String str) //去除字符串两端的空白符,空字符串、null 返回""
strip(String str, String stripChars) //去掉str两端的在stripChars中的字符
StringUtils.strip("000000134_76539000","0")="134_76539"

stripStart (String str,String stripChars) //去除str 前端在stripChars中的字符
stripEnd (String str,String stripChars) //去除str 后端在stripChars中的字符
equals(String str1,String str2) //比较两个字符串是否相等,如果两个均为空则认为相等
indexOf(String str,char searchChar) //返回searchChar 在字符串中第一次出现的位置,如果没找到则返回 -1,如果str 为null 或者 "",也返回-1
indexOf(String str,char searchChar,int startPos) //返回字符searchChar从startPos开始在字符串str中第一次出现的位置。
contains(String str,char searchChar) //str中是否包含字符searchChar,str为null 或者 searchChar为null,返回false 。
StringUtils.contains("", "") = true
StringUtils.contains("dfg", "") = true

containsIgnoreCase(String str,String searchStr) //str中是否包含字符searchChar,不区分大小写
int indexOfAny(String str, char[] searchChars) //找出字符数组searchChars中的字符第一次出现在字符串str中的位置。 如果字符数组中的字符都不在字符串中,则返回-1 ,如果字符串为null或"",则返回-1
subString(String str,int start) //从start 开始,包含start 那个字符,得到字符串str 的子串,如果start为负数,则从后面开始数起。如果str 为null 或者 "" 则返回其本身
subStringBefore(String str,String separator) //得到字符串separator第一次出现前的子串。不包含那个字符,如果str 为null 或者 "" 则返回其本身。
subStringAfter(String str,String separator) //得到字符串separator第一次出现后的子串,不包含那个字符,如果 str 为null,或者"",则返回其本身
subString(String str,int start,int end) //同上
left(String str,int len) //得到字符串str从左边数len长度的子串,如果str 为null 或者 "",则返回其本身,如果len小于0,则返回""
right(String str,int len) //得到字符串str从右边数len长度的子串
mid(String str,int pos,int len) //得到字符串str从pos开始len长度的子串,pos小于0,则设为0。
split(String str) //把字符串拆分成一个字符串数组,用空白符 作为分隔符,字符串为null 返回null,字符串为"",返回空数组{}
split(String str,char c) //按照 char c 拆分字符串
join(Object[] arrey) //把数组中的元素连接成一个字符串返回
join(Object[] arrey,char c) //把数组中的元素拼接成一个字符串返回,把分隔符 c 也带上
deleteWhitespace(String str) //删除字符串中的所有空白符,包括转义字符
removeStart(String str,String remove) //如果字符串str是以remove开始,则去掉这个开始,然后返回,否则返回原来的串
removeEnd(String str,String remove) //如果字符串str是以字符串remove结尾,则去掉这个结尾,然后返回,否则返回原来的串。
remove(String str,char remove) //去掉字符串str中所有包含remove的部分,然后返回
replace(String str,String reql,String with) //在字符串text中用with代替repl,替换所有
replaceChars(String str,char old,char new) //在字符串中 new 字符代替 old 字符
replaceChars(String str, String searchChars, String replaceChars) //这个有点特别,先看下面三个例子
StringUtils.replaceChars("asssdf","s","yyy")) = "ayyydf"
StringUtils.replaceChars("asdf","sd","y")) = "ayf"
StringUtils.replaceChars("assssddddf","sd","y"))= "ayyyyf"
//解释:为什么会出现上面这样的结果呢?原来这个置换规则是这样的,他是拿searchChars的index,去replaceChars找相应的index然后替换掉,怎么说呢?比如说第一个例子 s 的index 是0,找到yyy相对应的index为0的字符是y。第二个例子 's' 的index是0,'d'的index是1, 字符's' 可以找到对应index为0的 'y',d就找不到index为'1'的的字符了,所以就直接过滤掉了,听明白了吗?

overlay(String str,String new,int start,int end) //用字符串new 覆盖字符串str从start 到 end 之间的串
chop(String str) //去掉字符串的最后一个字符,比如/r/n
repeat(String str,int repart) //重复字符串repeat次
rightPad(String str,int size,String padStr) //size长度的字符串,如果不够用padStr补齐
leftPad(String str,int size,String padStr) //同上
center(String str,int size) //产生一个字符串,长度等于size,str位于新串的中心
swapCase(String str) //字符串中的大写转小写,小写转换为大写

IOUtils

import org.apache.tomcat.util.http.fileupload.IOUtils;

try {
    InputStream inputStream = new FileInputStream("d:/test.txt");
    OutputStream outputStream = new FileOutputStream(new File("d:/test_copy.txt"));
    IOUtils.copy(inputStream,outputStream);
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

RandomStringUtils

//产生5位长度的随机字符串,中文环境下是乱码[/b]
RandomStringUtils.random(5);
 
//使用指定的字符生成5位长度的随机字符串[/b]
RandomStringUtils.random(5, new char[]{'a','b','c','d','e','f', '1', '2', '3'});
 
//生成指定长度的字母和数字的随机组合字符串[/b]
RandomStringUtils.randomAlphanumeric(5);
 
//生成随机数字字符串[/b]
RandomStringUtils.randomNumeric(5);
 
//生成随机[a-z]字符串,包含大小写[/b]
RandomStringUtils.randomAlphabetic(5);
 
//生成从ASCII 32到126组成的随机字符串 [/b]
RandomStringUtils.randomAscii(4)
 
for (int i = 0;i<10;i++) {
	System.out.println(RandomStringUtils.randomAlphanumeric(5).toLowerCase());
}

Lists

// 依赖:
/**
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.1-jre</version>
</dependency>
*/
import com.google.common.collect.Lists;
List<User> userList = Lists.newArrayList(
        new User().setId("A").setName("张三"),
        new User().setId("B").setName("李四"),
        new User().setId("C").setName("王五")
);

Strings

// 创建空字符串
String str = Strings.EMPTY;
// 拆分字符串,如果要拆分:"com.fzai.test" 型式的字符串,"." 要加上转义字符 "\\."
String name = "com.fzai.test";
name.split("\\.");

FastJson

// 解决将对象转换成JSON字符串时出现  $ref 字符的问题:
JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect); 

//JSONObject转对象
String JSONStr = JSON.toJSONString(jsonObject);
BusLine busLine = JSON.parseObject(JSONStr, BusLine.class);

// JSONArray转对象集合
String JSONStr = JSON.toJSONString(jsonArray);
List<BusLine> busLineList = JSON.parseObject(JSONStr,new TypeReference<List<BusLine>>(){});

Date

// 获取年月日
Date dt=new Date();
String year=String.format("%tY", dt);
String mon=String .format("%tm", dt);
String day=String .format("%td", dt);
System.out.println(year);
System.out.println(mon);
System.out.println(day);

Pattern

// 获取引号内的内容
public static List getContent(String str){
    Pattern p1=Pattern.compile("\"(.*?)\"");

    Matcher m = p1.matcher(str);
    StringBuilder stringBuilder = new StringBuilder();

    ArrayList<String> list = new ArrayList<String>();
    while (m.find()) {
        list.add(m.group().trim().replace("\"","")+" ");
    }
    return list;
}

stream

// 拆分字符串并将结果数组转换成Integer集合
String str = "1,2,3,4,5,6";
List<Integer> collect = Arrays.stream(StringUtils.split(str, ",")).map(Integer::parseInt).collect(Collectors.toList());

// 对象集合根据对象的某个字段去重
List<TermiteCensus> all = termiteCensusList.stream()
                        .collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                                new TreeSet<>(Comparator.comparingLong(TermiteCensus::getDbBasicInformationId))), ArrayList::new));

list

list.removeif()

//问题:有0,1,2,3,4五个人,需要从list中获取数据,要求每个人的数据中不包含他们本身。
//思路:将原数据集合list复制到result,然后从result移除数据;
//注意:不能直接使用list做removeif(),因为如果直接从list移除数据,会把list中的0,1,2,3,4都移除,导致最后一次操作之后list中只剩5,6,7。
ArrayList<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);
ArrayList<Integer> result = Lists.newArrayList();
for (int i = 0; i < 5; i++) {
    result.addAll(list);
    int finalI = i;
    result.removeIf(j -> j == finalI);
    System.err.println(result);
    result.clear();
}
System.err.println(">>>"+list);

list.clear()

字符串等值判断忽略大小写

String order = "asc";//String order = "ASC";
if("asc".equalsIgnoreCase(order){
  ...
}

long和int互转

Long a = 123L;
Integer b = 123;
int i = a.intValue();
long l = b.longValue();	

byte数组与InputStream之间的转换

https://blog.csdn.net/weixin_39911066/article/details/114800383

// 将File、FileInputStream 转换为byte[]数组:
File file = new File("file.txt");
InputStream input = new FileInputStream(file);
byte[] byt = new byte[input.available()];
input.read(byt);

// 将byte[]数组转换为InputStream:
byte[] byt = new byte[1024];
InputStream input = new ByteArrayInputStream(byt);

// 将byte[]数组转换为File:
File file = new File('');
OutputStream output = new FileOutputStream(file);
BufferedOutputStream bufferedOutput = new BufferedOutputStream(output);
bufferedOutput.write(byt);

// 字符串(String) 与 byte[] 数组
String str = "字符串与byte[]数组";
byte[] bytes = str.getBytes();
InputStream inputStream = new ByteArrayInputStream(bytes);
try {
ByteArrayOutputStream byteArrayOutputStream = new       ByteArrayOutputStream();
  byte[] buff = new byte[100];
  int rc = 0;
  while ((rc = inputStream.read(buff, 0, 100)) > 0) {
    byteArrayOutputStream.write(buff, 0, rc);
  }
  byte[] bytes1 = byteArrayOutputStream.toByteArray();
  String string = new String(bytes1, StandardCharsets.UTF_8);
  System.out.println("string = " + string);
} catch (IOException e) {
  System.out.println(e.toString());
}

项目启动时执行指定代码

@Order(value = 1)  // 根据value大小决定类执行顺序
@Component
public class MyApplicationRunner implements ApplicationRunner{
    @Override
    public void run(ApplicationArguments args) throws Exception{
        //假装有代码
    }
}

删除指定文件夹及文件夹下文件

/**
 * 删除目标文件夹下所有文件
 * @param file
 * @return
 */
public boolean deleteFile(File file){
    //判断文件不为null或文件目录存在
    if (file == null || !file.exists()){
        return false;
    }
    //取得这个目录下的所有子文件对象
    File[] files = file.listFiles();
    //遍历该目录下的文件对象
    if (files != null) {
        for (File f: files){
            //判断子目录是否存在子目录,如果是文件则删除
            if (f.isDirectory()){
                deleteFile(f);
            }else {
                f.delete();
            }
        }
    }
    //删除空文件夹  for循环已经把上一层节点的目录清空。
    file.delete();
    return true;
}

LocalDateTime获取前一天

http://www.yq1012.com/shizhan/4329.html

DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String timeNode = df.format(LocalDateTime.now().minusDays(1)); // 昨天
String timeNode = df.format(LocalDateTime.now().plusDays(1)); // 明天

实体对象转map

// fastjson
Map newMap = JSON.parseObject(JSON.toJSONString(newUser), Map.class);

从Timestamp获取年份

int year = Timestamp对象.getYear() + 1900;

获取当前年份

int now = Calendar.getInstance().get(Calendar.YEAR);

文件分隔符

File.separator
/**
 * File.separator 的作用相当于 ' \  '
 * 在 windows 中 文件文件分隔符 用 ' \ ' 或者 ' / ' 都可以
 * 但是在 Linux 中,是不识别 ' \ '  的,而 File.separator 是系统默认的文件分隔符号,在 UNIX 系统上,此字段的值为 ' / '
 * 所以用 File.separator 保证了在任何系统下不会出错。
 */
 /upload + File.separator + 20211105/test.zip
upload/20211105/test.zipt/.zip

文件大小转换

/**
 * 定义GB的计算常量
 */
private static final int GB = 1024 * 1024 * 1024;
/**
 * 定义MB的计算常量
 */
private static final int MB = 1024 * 1024;
/**
 * 定义KB的计算常量
 */
private static final int KB = 1024;
/**
 * 文件大小转换
 */
public static String getSize(long size) {
    String resultSize;
    if (size / GB >= 1) {
        //如果当前Byte的值大于等于1GB
        resultSize = DF.format(size / (float) GB) + "GB   ";
    } else if (size / MB >= 1) {
        //如果当前Byte的值大于等于1MB
        resultSize = DF.format(size / (float) MB) + "MB   ";
    } else if (size / KB >= 1) {
        //如果当前Byte的值大于等于1KB
        resultSize = DF.format(size / (float) KB) + "KB   ";
    } else {
        resultSize = size + "B   ";
    }
    return resultSize;
}

文件压缩

// 导包
import java.io.*;
import java.util.List;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import com.google.common.collect.Lists;

// 代码
List<File> files = Lists.newArrayList();
FileOutputStream f = null;
try {
    f = new FileOutputStream("D:\\test.zip");
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
CheckedOutputStream checkedOut = new CheckedOutputStream(f, new Adler32());
ZipOutputStream zipOut = new ZipOutputStream(checkedOut);
BufferedOutputStream bufferedOut = new BufferedOutputStream(zipOut);
try {
    for (File file : files) {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        try {
            // 设置文件名,如果为“aaa/bbb/ccc.txt”的形式,则会在test.zip中有对应的文件夹aaa、bbb
            zipOut.putNextEntry(new ZipEntry(file.getName()));
            byte[] buffer = new byte[1024];
            int i = bis.read(buffer);
            while (i != -1) {
                bufferedOut.write(buffer, 0, i);
                i = bis.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                bufferedOut.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        bufferedOut.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

创建多级文件夹

mkdirs()
比如在D盘创建文件夹 temp,在temp中又创建file,在file中又创建download:
new file("D:/temp/file/download").makirs();
如果使用mkdir就只能一级一级创建。

日期转换

// 各种日期格式
// 中国标准时间:Wed Feb 13 2019 16:49:31 GMT+0800
// 格林威治时间:Wed, 13 Feb 2019 08:49:31 GMT
// 国际标准组织(ISO)格式:2019-02-13T08:49:31.342Z

// String转Timestamp
Timestamp.valueOf(string);

// String转LocalDateTime
String date = "2020-05-24 10:43:12";
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime time = LocalDateTime.parse(date, df);
System.err.println(time);

// Date转LocalDateTime
//将java.util.Date 转换为java8 的java.time.LocalDateTime,默认时区为东8区
Date date = new Date();
date.toInstant().atOffset(ZoneOffset.of("+8")).toLocalDateTime();
//将java8 的 java.time.LocalDateTime 转换为 java.util.Date,默认时区为东8区
Date.from(LocalDateTime.now().toInstant(ZoneOffset.of("+8")));

// LocalDateTime 转 Timestamp
Timestamp.valueOf(LocalDateTime.now())
// Timestamp 转 LocalDateTime
Timestamp.from(Instant.now()).toLocalDateTime()

// LocalDateTime转Instant
import java.time.LocalDateTime; //导入方法依赖的package包/类
public static Instant parseDateInstant(String strDate) {
    LocalDateTime dateTime = parseDate(strDate);
    if (dateTime != null) {
        return dateTime.toInstant(ZoneOffset.UTC);
    }
    return null;
}

// LocalDateTime转字符串
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now())

// ISO时间转换成标准时间
Date parse = ISO8601Utils.parse(changeSafetyProblem.getAfterChange());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = dateFormat.format(parse);

String转数字类型

Integer.parseInt(str)
Long.parseLong(str)
Double.parseDouble(str)

array转list

Arrays.asList(array)

Object转Map

使用Apache中的BeanUtils类,导入commons-beanutils包

jar包的下载地址:https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils。

//1、map转换为object
public static Object mapToObject(Map<String, Object> map, Class<?> beanClass)
  throws Exception {
  if (map == null) {
    return null;
  }
  Object obj = beanClass.newInstance();
  org.apache.commons.beanutils.BeanUtils.populate(obj, map);
  return obj;
}
//2、object转换为map
public static Map<?, ?> objectToMap(Object obj) {
  if (obj == null) {
    return null;
  }
  return new org.apache.commons.beanutils.BeanMap(obj);
}

利用java.lang.reflect.Field类完成Obj和Map之间的相互转换

//1、object转换成map
public Map<String,Object> Obj2Map(Object obj) throws Exception{
  Map<String,Object> map=new HashMap<String, Object>();
  Field[] fields = obj.getClass().getDeclaredFields();
  for(Field field:fields){
    field.setAccessible(true);
    map.put(field.getName(), field.get(obj));
  }
  return map;
}
//2、map转换为object
public Object map2Obj(Map<String,Object> map,Class<?> clz) throws Exception{
  Object obj = clz.newInstance();
  Field[] declaredFields = obj.getClass().getDeclaredFields();
  for(Field field:declaredFields){
    int mod = field.getModifiers();
    if(Modifier.isStatic(mod) || Modifier.isFinal(mod)){
    continue;
    }
    field.setAccessible(true);
    field.set(obj, map.get(field.getName()));
  }
  return obj;
}

this::function

// this::function代表这个函数对象的方法,也可以用Object::function的方式。其中this::fuction不可以用在static方法上,而Object::function是用在Object类的static方法中。

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class Test {
	public static void printValur(String str) {
		System.out.println("print value : " + str);
	}

	public static void main(String[] args) {
		List<String> al = Arrays.asList("a", "b", "c", "d");
		al.forEach(Test::printValur);
		// 下面的方法和上面等价的
		Consumer<String> methodParam = Test::printValur; // 方法参数
		al.forEach(x -> methodParam.accept(x));// 方法执行accept
	}
}

HttpServletResquest、HttpServletResponse

@RequestMapping("/getTest")
publicResultgetTest(HttpServletResponseresponse,HttpServletRequestrequest){
  try{
    System.err.println(response.getStatus());//200
    System.err.println("---------------------");
    System.err.println(request.getRemoteAddr());//远程ip
    System.err.println(request.getRemoteHost());//远程主机
    System.err.println(request.getRemotePort());//远程端口
    System.err.println(request.getRemoteUser());//远程用户
    System.err.println(request.getRequestURI());//远程接口:/GCDA/getTest
    System.err.println(request.getRequestURL());//远程地址:http://192.168.0.29:8082/GCDA/getTest
    System.err.println(request.getServerName());//192.168.0.29
    System.err.println(request.getServerPort());//8082
    returnnewResult(true,MessageConstant.QUERY_GCDA_SUCCESS);
  }catch(Exceptione){
    e.printStackTrace();
    returnnewResult(false,MessageConstant.QUERY_GCDA_FAIL);
  }
}

String长度限制

String 类型长度不能大于等于65535,否则会编译失败。

数组转String并设置字符串编码

使用String类的构造方法:

byte[] bytes = new byte[]{72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100};
String str = new String(bytes);
System.out.println(str); // Hello World

str = new String(bytes, Charset.forName("UTF-8"));
System.out.println(str); // Hello World

使用编码类:

byte[] bytes = new byte[]{72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100};
Charset charset = Charset.forName("UTF-8");
ByteBuffer buffer = ByteBuffer.wrap(bytes);
String str = charset.decode(buffer).toString();
System.out.println(str); // Hello World

修改war包内容

1、将war包移动到一个干净的路径下,使用 jar xvf ROOT.war 命令将war进行解压操作。
2、修改相应的文件内容,修改想要修改的文件,比如web.xml。
3、使用 jar uvf ROOT.war WEB-INF/web.xml 将web.xml重新压缩到war包。

全局时间格式化

https://mp.weixin.qq.com/s/MeDfnL__jdEq7Yi48vg_vA

@JsonFormat 注解

       @JsonFormat注解方式严格意义上不能叫全局时间格式化,应该叫部分格式化,因为@JsonFormat注解 需要用在实体类的时间字段上,而只有使用相应的实体类,对应的字段才能进行格式化。

@Data
public class OrderDTO {
    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd")
    private LocalDateTime createTime;
    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

@JsonComponent 注解(推荐)

       使用 @JsonComponent 注解自定义一个全局格式化类,分别对 Date 和 LocalDate 类型做格式化处理。实际开发中如果有个字段不想用全局格式化设置的时间样式,想自定义格式怎么办?那就需要和 @JsonFormat 注解配合使用了。@JsonFormat 注解的优先级比较高,会以 @JsonFormat 注解的时间格式为主。

@JsonComponent
public class DateFormatConfig {
    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;
    /**
     * @author xiaofu
     * @description date 类型全局时间格式化
     * @date 2020/8/31 18:22
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilder() {
        return builder -> {
            TimeZone tz = TimeZone.getTimeZone("UTC");
            DateFormat df = new SimpleDateFormat(pattern);
            df.setTimeZone(tz);
            builder.failOnEmptyBeans(false)
                    .failOnUnknownProperties(false)
                    .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                    .dateFormat(df);
        };
    }
    /**
     * @author xiaofu
     * @description LocalDate 类型全局时间格式化
     * @date 2020/8/31 18:22
     */
    @Bean
    public LocalDateTimeSerializer localDateTimeDeserializer() {
        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
    }
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer());
    }
}

@Configuration 注解

这种全局配置的实现方式与上边的效果是一样的。但是在使用此种配置后,字段手动配置@JsonFormat 注解将不再生效。

@Configuration
public class DateFormatConfig2 {
    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;
    public static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Bean
    @Primary
    public ObjectMapper serializingObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }
    /**
     * @author xiaofu
     * @description Date 时间类型装换
     * @date 2020/9/1 17:25
     */
    @Component
    public class DateSerializer extends JsonSerializer<Date> {
        @Override
        public void serialize(Date date, JsonGenerator gen, SerializerProvider provider) throws IOException {
            String formattedDate = dateFormat.format(date);
            gen.writeString(formattedDate);
        }
    }
    /**
     * @author xiaofu
     * @description Date 时间类型装换
     * @date 2020/9/1 17:25
     */
    @Component
    public class DateDeserializer extends JsonDeserializer<Date> {
        @Override
        public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            try {
                return dateFormat.parse(jsonParser.getValueAsString());
            } catch (ParseException e) {
                throw new RuntimeException("Could not parse date", e);
            }
        }
    }
    /**
     * @author xiaofu
     * @description LocalDate 时间类型装换
     * @date 2020/9/1 17:25
     */
    public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeString(value.format(DateTimeFormatter.ofPattern(pattern)));
        }
    }
    /**
     * @author xiaofu
     * @description LocalDate 时间类型装换
     * @date 2020/9/1 17:25
     */
    public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
        @Override
        public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException {
            return LocalDateTime.parse(p.getValueAsString(), DateTimeFormatter.ofPattern(pattern));
        }
    }
}

两个字符串相似度

https://blog.csdn.net/daiyi666/article/details/119778443

/**
 * 字符串相似度
 *
 * @param sourceString /
 * @param targetString /
 * @return /
 */
public static double getStringSimilarity(String sourceString, String targetString) {
    int[][] matrix;
    int sourceStringLength = sourceString.length();
    int targetStringLength = targetString.length();
    int indexOfSourceString;
    int indexOfTargetString;
    char charOfSourceString;
    char charOfTargetString;
    int temp;

    if (sourceStringLength == 0 || targetStringLength == 0) return 0;

    matrix = new int[sourceStringLength + 1][targetStringLength + 1];
    for (indexOfSourceString = 0; indexOfSourceString <= sourceStringLength; indexOfSourceString++) {
        matrix[indexOfSourceString][0] = indexOfSourceString;
    }
    for (indexOfTargetString = 0; indexOfTargetString <= targetStringLength; indexOfTargetString++) {
        matrix[0][indexOfTargetString] = indexOfTargetString;
    }

    for (indexOfSourceString = 1; indexOfSourceString <= sourceStringLength; indexOfSourceString++) {
        charOfSourceString = sourceString.charAt(indexOfSourceString - 1);
        for (indexOfTargetString = 1; indexOfTargetString <= targetStringLength; indexOfTargetString++) {
            charOfTargetString = targetString.charAt(indexOfTargetString - 1);
            if (charOfSourceString == charOfTargetString || charOfSourceString == charOfTargetString + 32 || charOfSourceString + 32 == charOfTargetString) {
                temp = 0;
            } else temp = 1;
            matrix[indexOfSourceString][indexOfTargetString] = Math.min(Math.min(matrix[indexOfSourceString - 1][indexOfTargetString] + 1, matrix[indexOfSourceString][indexOfTargetString - 1] + 1), matrix[indexOfSourceString - 1][indexOfTargetString - 1] + temp);
        }
    }
    return (1 - (double) matrix[sourceStringLength][targetStringLength] / Math.max(sourceString.length(), targetString.length())) * 100F;
}

全部评论

搜索