参考:java中排序函数sort()使用
常见sort:
参考:
Java的Comparator升序降序的记法
leetcode56合并区间
sort函数中使用的cmp
1、通常写法
import java.util.Comparator;
class MyComparator implements Comparator<A> {
@Override
public int compare(A o1, A o2) {
//升序
//return o1.a - o2.a;
//降序:后面会具体分析为什么降序
return o2.a - o1.a;
}
}
// 使用
Collections.sort(list, new MyComparator())
这里o1表示位于前面的对象,o2表示后面的对象
2、高级写法
lamda:
// 先按照区间起始位置排序
Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);
解释:
v1[0] - v2[0]即升序排列,因为v1[0]
Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);假设传来两个值,v1与v2,那么他们的先后顺序以v1[0]比v2[0]的结果为准,即:若v1[0] < v2[0]则v1 < v2,若=则=,若>则>
举一反三:Arrays.sort(intervals, (v1, v2) -> v1[0] == v2[0] ? v1[1] - v2[1] : v1[0] - v2[0]);
表示:传来两个值 v1
与 v2
,若 [0]
相同,则按 [1]
升序;若不同则按 [0]
升序。
class MyComparator implements Comparator<int[]> {
@Override
public int compare(int[] a1, int[] a2) {
if (a1[0] == a2[0]) {
return a1[1] - a2[1];
} else {
return a1[0] - a2[0];
}
}
}
参考:
Java Lambda 表达式
语法:
(parameters) -> expression
或
(parameters) ->{ statements; }
例子:
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
参考:
菜鸟——java
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。它还提供了快速基于索引访问元素的方式,对尾部成员的增加和删除支持较好。使用 ArrayList 创建的集合,允许对集合中的元素进行快速的随机访问,不过,向 ArrayList 中插入与删除元素的速度相对较慢。
方法 | 描述 |
---|---|
add() | 将元素插入到指定位置的 arraylist 中 |
addAll() | 添加集合中的所有元素到 arraylist 中 |
clear() | 删除 arraylist 中的所有元素 |
clone() | 复制一份 arraylist |
contains() | 判断元素是否在 arraylist |
get() | 通过索引值获取 arraylist 中的元素 |
indexOf() | 返回 arraylist 中元素的索引值 |
removeAll() | 删除存在于指定集合中的 arraylist 里的所有元素 |
remove() | 删除 arraylist 里的单个元素 |
size() | 返回 arraylist 里元素数量 |
isEmpty() | 判断 arraylist 是否为空 |
subList() | 截取部分 arraylist 的元素 |
set() | 替换 arraylist 中指定索引的元素 |
sort() | 对 arraylist 元素进行排序 |
forEach() | 遍历 arraylist 中每一个元素并执行特定操作(常使用lambda函数配合) |
LinkedList 类采用链表结构保存对象,这种结构的优点是便于向集合中插入或者删除元素。需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高,但是 LinkedList 类随机访问元素的速度则相对较慢。这里的随机访问是指检索集合中特定索引位置的元素。
非线程安全的
HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。HashSet 是无序的,即不会记录插入的顺序。
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
方法 | 描述 |
---|---|
clear() | 删除 hashMap 中的所有键/值对 |
clone() | 复制一份 hashMap |
isEmpty() | 判断 hashMap 是否为空 |
size() | 计算 hashMap 中键/值对的数量 |
put() | 将键/值对添加到 hashMap 中 |
putAll() | 将所有键/值对添加到 hashMap 中 |
putIfAbsent() | 如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中。 |
remove() | 删除 hashMap 中指定键 key 的映射关系 |
containsKey() | 检查 hashMap 中是否存在指定的 key 对应的映射关系。 |
containsValue() | 检查 hashMap 中是否存在指定的 value 对应的映射关系。 |
replace() | 替换 hashMap 中是指定的 key 对应的 value。 |
replaceAll() | 将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。 |
get() | 获取指定 key 对应对 value |
forEach() | 对 hashMap 中的每个映射执行指定的操作。 |
---|---|
entrySet() | 返回 hashMap 中所有映射项的集合集合视图。 |
keySet() | 返回 hashMap 中所有 key 组成的集合视图。 |
values() | 返回 hashMap 中存在的所有 value 值。 |
参考:
HashSet、LinkedHashSet和TreeSet三者区别与联系
三者都保证了元素的唯一性,如果无排序要求可以选用HashSet;如果想取出元素的顺序和放入元素的顺序相同,那么可以选用LinkedHashSet。如果想插入、删除立即排序或者按照一定规则排序可以选用TreeSet。
参考:list初始化
1)常规方式
List<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("PHP");
2)Arrays.asList
List<String> numbers = new ArrayList<>(Arrays.asList("1", "2", "3"));
numbers.add("4");
3)匿名内部类——双括号初始化
List<String> names = new ArrayList<>() {{
add("Tom");
add("Sally");
add("John");
}};
4)List.of
List<String> cups = List.of("A", "B", "C");
参考:map初始化
1、常规添加
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", "test");
map.put("age", "20");
2、双括号
HashMap<String, String> map = new HashMap<String, String>() {
{
put("name", "test");
put("age", "20");
}
};
3、Map.of
HashMap<String, Integer> map = Map.of("Hello", 1, "World", 2);//不可变集合
参考:
廖雪峰 java
大白话说java反射
反射:反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。反射的目的是为了获得某个实例的信息。
public class Apple {
private int price;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public static void main(String[] args) throws Exception{
//正常的调用
Apple apple = new Apple();
apple.setPrice(5);
System.out.println("Apple Price:" + apple.getPrice());
//使用反射调用
// 1、获取CLass对象实例
Class clz = Class.forName("com.chenshuyi.api.Apple");
// 2、获取方法的 Method 对象
Method setPriceMethod = clz.getMethod("setPrice", int.class);
// 3、根据 Class 对象实例获取 Constructor 对象
Constructor appleConstructor = clz.getConstructor();
// 4、使用 Constructor 对象的 newInstance 方法获取反射类对象
Object appleObj = appleConstructor.newInstance();
// 5、利用 invoke 方法调用方法
setPriceMethod.invoke(appleObj, 14);
Method getPriceMethod = clz.getMethod("getPrice");
System.out.println("Apple Price:" + getPriceMethod.invoke(appleObj));
}
}
Class clz = Class.forName("java.lang.String");
Class clz = String.class;
String str = new String("Hello");
Class clz = str.getClass();
两种方式:
Class clz = Apple.class;
Apple apple = (Apple)clz.newInstance();
Class clz = Apple.class;
Constructor constructor = clz.getConstructor();
Apple apple = (Apple)constructor.newInstance();
Apple apple2 = (Apple)constructor.newInstance("红富士", 15);
1、获得属性
Class clz = Apple.class;
Field[] fields = clz.getFields();
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
// getFields结果:price
// getDeclaredFields结果:name\n price
2、获得方法
Method getMethod(name, Class...)
:获取某个public
的Method
(包括父类)Method getDeclaredMethod(name, Class...)
:获取当前类的某个Method
(不包括父类)Method[] getMethods()
:获取所有public
的Method
(包括父类)Method[] getDeclaredMethods()
:获取当前类的所有Method
(不包括父类)3、获得构造方法
getConstructor(Class...)
:获取某个public
的Constructor
;getDeclaredConstructor(Class...)
:获取某个Constructor
;getConstructors()
:获取所有public
的Constructor
;getDeclaredConstructors()
:获取所有Constructor
。参考:
廖雪峰
深入浅出java注解
注解(Annotation)是放在Java源码的类、方法、字段、参数前的一种特殊“注释”
参考:
Fastjson 简明教程 | 菜鸟教程
高性能JSON框架之FastJson的简单使用
fastJSON,使用TypeReference处理复杂的泛型对象
序列化:就是将对象转化成字节序列的过程。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。核心作用是对象状态的保存与重建。
**反序列化:**就是讲字节序列转化成对象的过程。
在实际工作场景中,序列化和反序列化是一个十分常见常用的功能,现如今大部分都在采纳Json和FastJson解析库结合的这种方式进行交互,但是对于Java中Serializable的基本性质还是需要了解。
那么为什么要去进行序列化呢?有以下两个原因
Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。
具体例子可以参考:高性能JSON框架之FastJson的简单使用
@Test
public void whenJson_thanConvertToObjectCorrect() {
Person person = new Person(20, "John", "Doe", new Date());
// 对象装字符串
String jsonObject = JSON.toJSONString(person);
// 字符串转对象
Person newPerson = JSON.parseObject(jsonObject, Person.class);
assertEquals(newPerson.getAge(), 0); // 如果我们设置系列化为 false
assertEquals(newPerson.getFullName(), listOfPersons.get(0).getFullName());
}
//
此外,还会使用TypeReference处理复杂的泛型对象。
参考:
Lombok介绍及使用方法
java @Data注解
lombok到底是个什么呢,lombok是一个可以通过简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 Java 代码的工具,简单来说,比如我们新建了一个类,然后在其中写了几个字段,然后通常情况下我们需要手动去建立getter和setter方法啊,构造函数啊之类的。
lombok的作用就是为了省去我们手动创建这些代码的麻烦,它能够在我们编译源码的时候自动帮我们生成这些方法。
@Data : 注在类上,自动为所有字段添加@ToString, @EqualsAndHashCode, @Getter方法,为非final字段添加@Setter,和@RequiredArgsConstructor
@AllArgsConstructor : 注在类上,提供类的全参构造
@NoArgsConstructor : 注在类上,提供类的无参构造
@Getter / @Setter: 自动生成Getter/Setter方法
@EqualsAndHashCode : 注在类上,提供对应的 equals 和 hashCode 方法
@NonNull: 可以帮助我们避免空指针。
@Cleanup: 自动帮我们调用close()
方法,用于InputStream等场景
参考:
Java常用包及其类总结
【Java】JDK中常用包及其类和功能详细剖析
1.java.lang包,最基础的包、核心类库。常用类有String、Math、Thread、Object、包装类Integer、Character等,常用接口有Runnable、Iterable、Comparable。
2.java.util包,实用工具包。常用类有Arrays、Scanner、Random、HashSet、HashMap、ArrayList、Date等,常用接口有Collection、Set、List等。
3.java.io包,提供数据输入输出。常用类有File、FileInputStream、Reader等提供文件、字节输入输出的类。
4.java.net包,为网络连接提供服务。常用类有Socket、ServerSocket、URL等。
5.java.sql包,连接数据库的包。要实现jdbc类库。
6.java.awt、(javax.awt)包,创建用户界面、绘图的。常用类有Button、Panel、(JButton、JPanel)等。
参考:# java | 什么是动态代理?
背景:
Spring对接口类型使用JDK动态代理,对普通类使用CGLIB创建子类。
JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
CGLib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
代理模式在 Java 领域很多地方都有应用,它分为静态代理和动态代理,其中 Spring AOP 就是动态代理的典型例子。动态代理又分为接口代理和 cglib (子类代理)。
代理模式在我们日常中很常见,生活处处有代理:
无论是黄牛、外卖骑手都得帮我们干活。但是他们不能一手包办(比如黄牛不能帮我吃饭),他们只能做我们不能或者不想做的事。
所以,你看。代理模式其实就是当前对象不愿意做的事情,委托给别的对象做。
代理类实现了抽象角色的接口,导致代理类无法通用。比如,我的狗病了,想去看医生,但是排队挂号很麻烦,我也想有个黄牛帮我的排队挂号看病,但是黄牛它不懂这只狗的特性(黄牛跟狗不是同一类型,黄牛属于 Human 但狗属于 Animal 类)但排队挂号和排队买票相对于黄牛来说它两就是一件事,这个方法是不变的,现场排队。
如静态代理的内容所描述的,静态代理受限于接口的实现。动态代理就是通过使用反射,动态地获取抽象接口的类型,从而获取相关特性进行代理。因动态代理能够为所有的委托方进行代理。
使用动态代理有三个要点,
必须实现 InvocationHandler 接口,表明该类是一个动态代理执行类。
InvocationHandler 接口内有一实现方法如下: public Object invoke(Object proxy, Method method, Object[] args) 。使用时需要重写这个方法
获取代理类,需要使用 Proxy.newProxyInstance(Clas loader, Class>[] interfaces, InvocationHandler h) 这个方法去获取Proxy对象(Proxy 类类型的实例)
与基于接口实现类不同的是:
参考:
浅谈java中注解和python中装饰器的区别
总结
第一点:对代码块的影响
java注解:不会对所修饰的代码产生直接的影响。
python装饰器:可以对所修饰的代码产生直接的影响。
第二点:共通处
java中注解+反射 可以实现 python装饰器同样的功能,包括面向切面编程、参数校验等。
第三点:从用途看
****从用途看注解像是注释文档一样,用于生成javadoc文档(以参数形式标注)、检查等。
装饰器像是为函数提供更多的功能,并装在不同的函数身上。
第四点:从原理看
java注解:所有注解本质是继承自接口(Annotation)的接口
python装饰器:被装饰函数的返回值 作为参数传给闭包函数执行(这个闭包函数名前面加个@,就是装饰器)
参考:
StringUtils中isEmpty和isBlank的区别
Common-lang3工具类
CollectionUtils用法
import org.apache.commons.lang3.StringUtils;
System.out.println(StringUtils.isEmpty(null)); //true
System.out.println(StringUtils.isEmpty("")); //true
System.out.println(StringUtils.isEmpty(" ")); //false
System.out.println(StringUtils.isBlank(null)); //true
System.out.println(StringUtils.isBlank("")); //true
System.out.println(StringUtils.isBlank(" ")); //true
1、CollectionUtils.isEmpty的用法
public static boolean isEmpty(Collection coll) {
return coll == null || coll.isEmpty();
}
CollectionUtils.isEmpty(集合) 用来对集合null和空的判断.
2)常用方法
参考:
collection.stream()以及collect()方法
stream介绍,以及lambda表达式的使用
Java 8 Lambda 表达式及 Stream 在集合中的用法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VrT3QeUw-1662296124739)(images/java编程常用知识补充.assets/image-20220824191559008.png)]
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。
流(stream)的操作类型分为两种:
接下来,当把一个数据结构包装成 Stream 后,就要开始对里面的元素进行各类操作了。常见的操作可以归类如下。
Intermediate:
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
Terminal:
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
Short-circuiting:
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AXeAnC8Y-1662296124740)(images/java编程常用知识补充.assets/image-20220812104656824.png)]
1、filter
filter 对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream
//留下偶数,经过条件“被 2 整除”的 filter,剩下的数字为 {2, 4, 6}。
Integer[] sixNums = {1, 2, 3, 4, 5, 6};
Integer[] evens =Stream.of(sixNums).filter(n -> n%2 == 0).toArray(Integer[]::new);
//把每行的单词用 flatMap 整理到新的 Stream,然后保留长度不为 0 的,就是整篇文章中的全部单词了。
//REGEXP为正则表达式,具体逻辑具体分析
List<String> output = reader.lines().
flatMap(line -> Stream.of(line.split(REGEXP))).
filter(word -> word.length() > 0).collect(Collectors.toList());
2、Collectors.toMap
参考:Stream流Collectors.toMap用法
使用toMap()函数之后,返回的就是一个Map了,自然会需要key和value。
在.collect(Collectors.toMap(Person::getId, v -> v, (a,b)->a))
中:
第一个参数:Person:getId表示选择Person的getId作为map的key值;
第二个参数:v->v表示选择将原来的对象作为Map的value值
第三个参数:(a,b)->a中,如果a与b的key值相同,选择a作为那个key所对应的value值。
3、findFirst、orElse、orElseThrow
总是返回 Stream 的第一个元素,如果找不到则可以利用orElse或orElseThrow返回默认值或异常。
orElseThrow
PoAdjustRecord poAdjustRecord = poAdjustRecordList.stream()
.filter(poAdjustRecord1 -> Objects.equals(AdjustDataTypeEnum.AFTER_ADJUST_VALUE.getType(), poAdjustRecord1.getAdjustDataType()))
.findFirst().orElseThrow(() -> new ErpRuntimeException(ErrorCodeConstant.SAVE_ADJUST_RECORD_INFO_ERROR))
orElse
UserDTO userDTO = users.stream().filter(u -> u.getId() == uid).findFirst().orElse(null);
min/max/distinct
min 和 max 的功能也可以通过对 Stream 元素先排序,再 findFirst 来实现,但前者的性能会更好,为 O(n),而 sorted 的成本是 O(n log n)。同时它们作为特殊的 reduce 方法被独立出来也是因为求最大最小值是很常见的操作。
使用 distinct 来找出不重复的单词
例子:
List<String> widgetIds = widgets.stream().map(Widget::getWidgetId).collect(Collectors.toList());
List<String> list= Arrays.asList("a", "b", "c", "d");
List<String> collect =list.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(collect); //[A, B, C, D]
List<Integer> num = Arrays.asList(1,2,3,4,5);
List<Integer> collect1 = num.stream().map(n -> n * 2).collect(Collectors.toList());
System.out.println(collect1); //[2, 4, 6, 8, 10]
解释下一这行代码:
本来想要获得wiget的id集合,按照我的思路肯定是遍历widges,依次取得widgetIds,但是此行代码更加简洁,高效
参考:
Beanutils.copyProperties( )用法及重写提高效率
BeanUtils使用
如果你有两个具有很多相同属性的JavaBean,一个很常见的情况就是Struts里的PO对象(持久对象)和对应的ActionForm。例如:一个用户注册页面,有一个User实体类和一个UserActionForm,我们一般会在Action里从ActionForm构造一个PO对象,传统的方式是使用类似下面的语句对属性逐个赋值:
// 获取 ActionForm 表单数据
UserActionForm uForm = (UserActionForm) form;
// 构造一个User对象
User user = new User();
// 逐一赋值
user.setUsername(uForm.getUsername);
user.setPassword(uForm.getPassword);
user.setAge(uForm.getAge);
...........
...........
// 然后调用JDBC、或操作Hibernate 持久化对象User到数据库
HibernateDAO.save(user);
使用 BeanUtils.copyProperties() 方法以后,代码量大大的减少,而且整体程序看着也简洁明朗,代码如下:
// 获取 ActionForm 表单数据
UserActionForm uForm = (UserActionForm) form;
// 构造一个User对象
User user = new User();
BeanUtils.copyProperties(uForm,user);
// 然后调用JDBC、或操作Hibernate 持久化对象User到数据库
HibernateDAO.save(user);
注:如果User和UserActionForm 间存在名称不相同的属性,则BeanUtils不对这些属性进行处理,需要手动处理。例如:
User类里面有个createDate 创建时间字段,而UserActionForm里面无此字段。BeanUtils.copyProperties()不会对此字段做任何处理。必须要自己手动处理。
user.setModifyDate(new Date());
参考:菜鸟string
1)valueof
返回给定data type类型x参数的字符串表示形式。
ouble d = 1100.00;
boolean b = true;
long l = 1234567890;
char[] arr = {'r', 'u', 'n', 'o', 'o', 'b' };
System.out.println("返回值 : " + String.valueOf(d) );
System.out.println("返回值 : " + String.valueOf(b) );
System.out.println("返回值 : " + String.valueOf(l) );
System.out.println("返回值 : " + String.valueOf(arr) );
参考:
Java8 CompletableFuture 用法全解(介绍的很详细、之后可以细看)
Java 8 CompletableFuture 教程
在Java中CompletableFuture用于异步编程,异步编程是编写非阻塞的代码,运行的任务在一个单独的线程,与主线程隔离,并且会通知主线程它的进度,成功或者失败。
在这种方式中,主线程不会被阻塞,不需要一直等到子线程完成。主线程可以并行的执行其他任务。
使用这种并行方式,可以极大的提高程序的性能。
CompletableFuture实现了CompletionStage接口和Future接口,前者是对后者的一个扩展,增加了异步回调、流式处理、多个Future组合处理的能力,使Java在处理多任务的协同工作时更加顺畅便利。
一、创建异步任务
1、Future.submit
2、supplyAsync / runAsync
二、异步回调
1、thenApply / thenApplyAsync
2、thenAccept / thenRun
3、 exceptionally
4、whenComplete
5、handle
三、组合处理
1、thenCombine / thenAcceptBoth / runAfterBoth
2、applyToEither / acceptEither / runAfterEither
3、thenCompose
4、allOf / anyOf
其他:
1、get和join的异同点
PS:
RuntimeException(运行时异常、非检查异常) 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。 如果出现 RuntimeException,那么一定是程序员代码书写导致的错误.
CheckedException:一般是外部错误,这种异常都发生在编译阶段,Java 编译器会强制程序去捕获此类异常,即会出现要求你把这段可能出现异常的程序进行 try catch
创建异步任务会创建子线程。子线程是异步执行的,主线程休眠等待子线程执行完成,子线程执行完成后唤醒主线程,主线程获取任务执行结果后退出。
1、supplyAsync / runAsync(商城代码中用了runAsync)
supplyAsync表示创建带返回值的异步任务的,相当于ExecutorService submit(Callable task) 方法,runAsync表示创建无返回值的异步任务,相当于ExecutorService submit(Runnable task)方法,这两方法的效果跟submit是一样的,测试用例如下(一般使用lambda表达式):
runAsync()
运行异步计算 如果你想异步的运行一个后台任务并且不想改任务返回任务东西,这时候可以使用 CompletableFuture.runAsync()
方法,它持有一个Runnable 对象,并返回 CompletableFuture
。// Using Lambda Expression
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// Simulate a long-running Job
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
System.out.println("I'll run in a separate thread than the main thread.");
});
CompletableFuture可以从全局的 ForkJoinPool.commonPool()获得一个线程中执行这些任务。 但是你也可以创建一个线程池并传给runAsync()
和supplyAsync()
方法来让他们从线程池中获取一个线程执行它们的任务。
Executor executor = Executors.newFixedThreadPool(10);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return "Result of the asynchronous computation";
}, executor);
商城代码:
CompletableFuture.runAsync(()->{
contractCapService.updateContractAmountByPreOrder(prePoDbList, prePoLineDbList,
ContractRecordTypeEnum.POSITIVE, ContractRecordFromEnum.PRE_SUBMIT);
}, ThreadPoolTraceExecutor.traceThreadPool()); //
使用 supplyAsync()
运行一个异步任务并且返回结果 当任务不需要返回任何东西的时候, CompletableFuture.runAsync()
非常有用。但是如果你的后台任务需要返回一些结果应该要怎么样?
CompletableFuture.supplyAsync()
就是你的选择。它持有supplier
并且返回CompletableFuture
,T
是通过调用 传入的supplier取得的值的类型。
2、allof
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4kV91hGb-1662296124740)(images/java编程常用知识补充.assets/image-20220728143249473.png)]
参考:
Java 枚举(enum) 详解7种常见的用法
用法三:向枚举中添加新方法(实习中遇到这种写法)
public enum Color {
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
// 普通方法
public static String getName(int index) {
for (Color c : Color.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
// get set 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
参考:
Java中List.forEach()方法使用
例子:
// 创建集合
List<String> list =Lists.newArrayList("a","b","c","d");
//1、正常遍历
list.forEach(item->System.out.println(item));
//2、条件遍历
list.forEach(item->{
if("b".equals(item)){
System.out.println(item);
}
结论:
参考:
Guava - Maps.newHashMap 和 new HashMap 区别
Map<String, Object> result = new HashMap<String,Object>();
Map<String, Object> result = Maps.newHashMap();
参考:
Java中Synchronized的用法
synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
详细例子见原文,笔记只做记录。
一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞
当一个线程访问对象的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该对象中的非synchronized(this)同步代码块
此时每个对象一把锁(对比修饰静态方法)
class SyncThread implements Runnable {
private static int count;
public SyncThread() {
count = 0;
}
public void run() {
synchronized(this) { /
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (count++));
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public int getCount() {
return count;
}
}
class AccountOperator implements Runnable{
private Account account;
public AccountOperator(Account account) {
this.account = account;
}
public void run() {
synchronized (account) {
account.deposit(500);
account.withdraw(500);
System.out.println(Thread.currentThread().getName() + ":" + account.getBalance());
}
}
}
Synchronized修饰一个方法很简单,就是在方法的前面加synchronized,public synchronized void method(){//todo}; synchronized修饰方法和修饰一个代码块类似,只是作用范围不一样,修饰代码块是大括号括起来的范围,而修饰方法范围是整个函数。
Synchronized作用于整个方法的写法。
写法一:
public synchronized void method()
{
// todo
}
写法二:
public void method()
{
synchronized(this) {
// todo
}
}
Synchronized也可修饰一个静态方法,用法如下:
public synchronized static void method() {
// todo
}
静态方法是属于类的而不属于对象的。同样的,synchronized修饰的静态方法锁定的是这个类的所有对象。
synchronized作用于一个类T时,是给这个类T加锁,T的所有对象用的是同一把锁
A. 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是**一个静态方法或一个类,则它取得的锁是对类**,该类所有的对象同一把锁。
B. 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。
C. 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
参考:Arrays.asList() 和Collections.singletonList()的区别
两者最大区别就是可变性和不可变性
参考:
java Collections.emptyList方法的使用及注意事项
返回一个空的List(使用前提是不会再对返回的list进行增加和删除操作)
1,new ArrayList()创建时有初始大小10,占用内存,emptyList()不用创建一个新的对象,可以减少内存开销;
2,方法返回一个emptyList()时,不会报空指针异常,如果直接返回Null,没有进行非空判断就会报空指针异常;
注意:此List与常用的List不同,它是Collections类里的静态内部类,在继承AbstractList后并没有实现add()、remove()等方法,所以返回的List不能进行增加和删除元素操作。
参考:java中equals方法的用法以及==的用法(转)
有两种用法说明:
(1)对于字符串变量来说,使用“==”和“equals()”方法比较字符串时,其比较方法不同。
“==”比较两个变量本身的值,即两个对象在内存中的首地址。
“equals()”比较字符串中所包含的内容是否相同。
(2)使用时为了防止空指针,一般是固定字符串在前:
"xxx".equals(f.getAttribute())