本文已经收录到github仓库,此仓库用于分享Java相关知识总结,包括Java基础、MySQL、Spring Boot、MyBatis、Redis、RabbitMQ等等,欢迎大家提pr和star!
github地址:https://github.com/Tyson0314/Java-learning
如果github访问不了,可以访问gitee仓库。
面向对象编程:面向对象的语言,一切皆对象,如果想要调用一个函数,函数必须属于一个类或对象,然后在使用类或对象进行调用。面向对象编程可能需要多写很多重复的代码行。
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("do something...");
}
};
函数式编程:在某些编程语言中,如js、c++,我们可以直接写一个函数,然后在需要的时候进行调用,即函数式编程。
在Java8以前,使用Collections
的sort方法对字符串排序的写法:
List<String> names = Arrays.asList("dabin", "tyson", "sophia");
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});
Java8 推荐使用lambda表达式,简化这种写法。
List<String> names = Arrays.asList("dabin", "tyson", "sophia");
Collections.sort(names, (String a, String b) -> b.compareTo(a)); //简化写法一
names.sort((a, b) -> b.compareTo(a)); //简化写法二,省略入参类型,Java 编译器能够根据类型推断机制判断出参数类型
可以看到使用lambda表示式之后,代码变得很简短并且易于阅读。
Functional Interface:函数式接口,只包含一个抽象方法的接口。只有函数式接口才能缩写成 Lambda 表达式。@FunctionalInterface 定义类为一个函数式接口,如果添加了第二个抽象方法,编译器会立刻抛出错误提示。
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
public class FunctionalInterfaceTest {
public static void main(String[] args) {
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("666");
System.out.println(converted);
}
/**
* output
* 666
*/
}
Comparator 和 Runnable,Java 8 为他们都添加了 @FunctionalInterface 注解,以用来支持 Lambda 表达式。
指定入参类型,并返回 boolean 值的函数式接口。用来组合一个复杂的逻辑判断。
Predicate<String> predicate = (s) -> s.length() > 0;
predicate.test("dabin"); // true
Java8 将 Comparator 升级成函数式接口,可以使用lambda表示式简化代码。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-05 23:24
*/
public class ComparatorTest {
public static void main(String[] args) {
Comparator<Person> comparator = Comparator.comparing(p -> p.firstName);
Person p1 = new Person("dabin", "wang");
Person p2 = new Person("xiaobin", "wang");
// 打印-20
System.out.println(comparator.compare(p1, p2));
// 打印20
System.out.println(comparator.reversed().compare(p1, p2));
}
}
class Person {
public String firstName;
public String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
Consumer 接口接收一个泛型参数,然后调用 accept,对这个参数做一系列消费操作。
Consumer 源码:
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
示例1:
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-05 23:41
*/
public class ConsumerTest {
public static void main(String[] args) {
Consumer<Integer> consumer = x -> {
int a = x + 6;
System.out.println(a);
System.out.println("大彬" + a);
};
consumer.accept(660);
}
/**
* output
* 666
* 大彬666
*/
}
示例2:在stream里,对入参做一些操作,主要是用于forEach,对传入的参数,做一系列的业务操作。
// CopyOnWriteArrayList
public void forEach(Consumer<? super E> action) {
if (action == null) throw new NullPointerException();
Object[] elements = getArray();
int len = elements.length;
for (int i = 0; i < len; ++i) {
@SuppressWarnings("unchecked") E e = (E) elements[i];
action.accept(e);
}
}
CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
list.add(1);
list.add(2);
//forEach需要传入Consumer参数
list
.stream()
.forEach(System.out::println);
list.forEach(System.out::println);
示例3:addThen方法使用。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-05 23:59
*/
public class ConsumersTest {
public static void main(String[] args) {
Consumer<Integer> consumer1 = x -> System.out.println("first x : " + x);
Consumer<Integer> consumer2 = x -> {
System.out.println("second x : " + x);
throw new NullPointerException("throw exception second");
};
Consumer<Integer> consumer3 = x -> System.out.println("third x : " + x);
consumer1.andThen(consumer2).andThen(consumer3).accept(1);
}
/**
* output
* first x : 1
* second x : 1
* Exception in thread "main" java.lang.NullPointerException: throw exception second
* at com.dabin.java8.ConsumersTest.lambda$main$1(ConsumersTest.java:15)
* ...
*/
}
使用 java.util.Stream
对一个包含一个或多个元素的集合做各种操作,原集合不变,返回新集合。只能对实现了 java.util.Collection
接口的类做流的操作。Map
不支持 Stream
流。Stream
流支持同步执行,也支持并发执行。
Filter的入参是一个
Predicate,用于筛选出我们需要的集合元素。原集合不变。filter 会过滤掉不符合特定条件的,下面的代码会过滤掉nameList
中不以大彬开头的字符串。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-06 00:05
*/
public class StreamTest {
public static void main(String[] args) {
List<String> nameList = new ArrayList<>();
nameList.add("大彬1");
nameList.add("大彬2");
nameList.add("aaa");
nameList.add("bbb");
nameList
.stream()
.filter((s) -> s.startsWith("大彬"))
.forEach(System.out::println);
}
/**
* output
* 大彬1
* 大彬2
*/
}
自然排序,不改变原集合,返回排序后的集合。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-06 00:05
*/
public class StreamTest1 {
public static void main(String[] args) {
List<String> nameList = new ArrayList<>();
nameList.add("大彬3");
nameList.add("大彬1");
nameList.add("大彬2");
nameList.add("aaa");
nameList.add("bbb");
nameList
.stream()
.filter((s) -> s.startsWith("大彬"))
.sorted()
.forEach(System.out::println);
}
/**
* output
* 大彬1
* 大彬2
* 大彬3
*/
}
逆序排序:
nameList
.stream()
.sorted(Comparator.reverseOrder());
对元素某个字段排序:
list.stream().sorted(Comparator.comparing(Student::getAge).reversed());
list.stream().sorted(Comparator.comparing(Student::getAge));
将每个字符串转为大写。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-06 00:05
*/
public class StreamTest2 {
public static void main(String[] args) {
List<String> nameList = new ArrayList<>();
nameList.add("aaa");
nameList.add("bbb");
nameList
.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
}
/**
* output
* AAA
* BBB
*/
}
验证 nameList 中的字符串是否有以大彬
开头的。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-06 00:05
*/
public class StreamTest3 {
public static void main(String[] args) {
List<String> nameList = new ArrayList<>();
nameList.add("大彬1");
nameList.add("大彬2");
boolean startWithDabin =
nameList
.stream()
.map(String::toUpperCase)
.anyMatch((s) -> s.startsWith("大彬"));
System.out.println(startWithDabin);
}
/**
* output
* true
*/
}
统计 stream
流中的元素总数,返回值是 long
类型。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-06 00:05
*/
public class StreamTest4 {
public static void main(String[] args) {
List<String> nameList = new ArrayList<>();
nameList.add("大彬1");
nameList.add("大彬2");
nameList.add("aaa");
long count =
nameList
.stream()
.map(String::toUpperCase)
.filter((s) -> s.startsWith("大彬"))
.count();
System.out.println(count);
}
/**
* output
* 2
*/
}
类似拼接。可以实现将 list
归约成一个值。它的返回类型是 Optional
类型。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-06 00:22
*/
public class StreamTest5 {
public static void main(String[] args) {
List<String> nameList = new ArrayList<>();
nameList.add("大彬1");
nameList.add("大彬2");
Optional<String> reduced =
nameList
.stream()
.sorted()
.reduce((s1, s2) -> s1 + "#" + s2);
reduced.ifPresent(System.out::println);
}
/**
* output
* 大彬1#大彬2
*/
}
flatMap 用于将多个Stream连接成一个Stream。
下面的例子,把几个小的list转换到一个大的list。
/**
* @description: 把几个小的list转换到一个大的list。
* @author: 程序员大彬
* @time: 2021-09-06 00:28
*/
public class StreamTest6 {
public static void main(String[] args) {
List<String> team1 = Arrays.asList("大彬1", "大彬2", "大彬3");
List<String> team2 = Arrays.asList("大彬4", "大彬5");
List<List<String>> players = new ArrayList<>();
players.add(team1);
players.add(team2);
List<String> flatMapList = players.stream()
.flatMap(pList -> pList.stream())
.collect(Collectors.toList());
System.out.println(flatMapList);
}
/**
* output
* [大彬1, 大彬2, 大彬3, 大彬4, 大彬5]
*/
}
下面的例子中,将words数组中的元素按照字符拆分,然后对字符去重。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-06 00:35
*/
public class StreamTest7 {
public static void main(String[] args) {
List<String> words = new ArrayList<String>();
words.add("大彬最强");
words.add("大彬666");
//将words数组中的元素按照字符拆分,然后对字符去重
List<String> stringList = words.stream()
.flatMap(word -> Arrays.stream(word.split("")))
.distinct()
.collect(Collectors.toList());
stringList.forEach(e -> System.out.print(e + ", "));
}
/**
* output
* 大, 彬, 最, 强, 6,
*/
}
并行流。stream
流是支持顺序和并行的。顺序流操作是单线程操作,串行化的流无法带来性能上的提升,通常我们会使用多线程来并行执行任务,处理速度更快。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-06 00:05
*/
public class StreamTest7 {
public static void main(String[] args) {
int max = 100;
List<String> strs = new ArrayList<>(max);
for (int i = 0; i < max; i++) {
UUID uuid = UUID.randomUUID();
strs.add(uuid.toString());
}
List<String> sortedStrs = strs.stream().sorted().collect(Collectors.toList());
System.out.println(sortedStrs);
}
/**
* output
* [029be6d0-e77e-4188-b511-f1571cdbf299, 02d97425-b696-483a-80c6-e2ef51c05d83, 0632f1e9-e749-4bce-8bac-1cf6c9e93afa, ...]
*/
}
Java8 针对 map 操作增加了一些方法,非常方便
1、删除元素使用removeIf()
方法。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-07 00:03
*/
public class MapTest {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "dabin1");
map.put(2, "dabin2");
//删除value没有含有1的键值对
map.values().removeIf(value -> !value.contains("1"));
System.out.println(map);
}
/**
* output
* {1=dabin1}
*/
}
2、putIfAbsent(key, value)
如果指定的 key 不存在,则 put 进去。
/**
* @description:
* @author: 程序员大彬
* @time: 2021-09-07 00:08
*/
public class MapTest1 {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "大彬1");
for (int i = 0; i < 3; i++) {
map.putIfAbsent(i, "大彬" + i);
}
map.forEach((id, val) -> System.out.print(val + ", "));
}
/**
* output
* 大彬0, 大彬1, 大彬2
*/
}
3、map 转换。
/**
* @author: 程序员大彬
* @time: 2021-09-07 08:15
*/
public class MapTest2 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("1", 1);
map.put("2", 2);
Map<String, String> newMap = map.entrySet().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> "大彬" + String.valueOf(e.getValue())));
newMap.forEach((key, val) -> System.out.print(val + ", "));
}
/**
* output
* 大彬1, 大彬2,
*/
}
4、map遍历。
/**
* @author: 程序员大彬
* @time: 2021-09-07 08:31
*/
public class MapTest3 {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "大彬1");
map.put(2, "大彬2");
//方式1
map.keySet().forEach(k -> {
System.out.print(map.get(k) + ", ");
});
//方式2
map.entrySet().iterator().forEachRemaining(e -> System.out.print(e.getValue() + ", "));
//方式3
map.entrySet().forEach(entry -> {
System.out.print(entry.getValue() + ", ");
});
//方式4
map.values().forEach(v -> {
System.out.print(v + ", ");
});
}
}
https://juejin.im/post/5c3d7c8a51882525dd591ac7#heading-16
最后给大家分享一个github仓库,上面放了200多本经典的计算机书籍,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~
github地址:https://github.com/Tyson0314/java-books
如果github访问不了,可以访问gitee仓库。