mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-08-10 00:41:37 +08:00
Compare commits
11 Commits
64405ffc3d
...
3758b7e635
Author | SHA1 | Date | |
---|---|---|---|
|
3758b7e635 | ||
|
247de7bc93 | ||
|
ba7ee51d86 | ||
|
55f136095c | ||
|
ae8766c479 | ||
|
86551a416c | ||
|
b0fd944be3 | ||
|
832d5cb7e0 | ||
|
9fbbdc679e | ||
|
dc82ce4fb2 | ||
|
2776b57028 |
@ -74,6 +74,7 @@
|
||||
- [CopyOnWriteArrayList 核心源码分析](./docs/java/collection/copyonwritearraylist-source-code.md)
|
||||
- [ArrayBlockingQueue 核心源码分析](./docs/java/collection/arrayblockingqueue-source-code.md)
|
||||
- [PriorityQueue 核心源码分析](./docs/java/collection/priorityqueue-source-code.md)
|
||||
- [DelayQueue 核心源码分析](./docs/java/collection/delayqueue-source-code.md)
|
||||
|
||||
### IO
|
||||
|
||||
|
@ -93,6 +93,7 @@ export default sidebar({
|
||||
"copyonwritearraylist-source-code",
|
||||
"arrayblockingqueue-source-code",
|
||||
"priorityqueue-source-code",
|
||||
"delayqueue-source-code",
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -58,6 +58,8 @@ tag:
|
||||
2. **提高了整体灵活性**:每一层都可以使用最适合的技术来实现,你只需要保证你提供的功能以及暴露的接口的规则没有改变就行了。**这个和我们平时开发系统的时候要求的高内聚、低耦合的原则也是可以对应上的。**
|
||||
3. **大问题化小**:分层可以将复杂的网络问题分解为许多比较小的、界线比较清晰简单的小问题来处理和解决。这样使得复杂的计算机网络系统变得易于设计,实现和标准化。 **这个和我们平时开发的时候,一般会将系统功能分解,然后将复杂的问题分解为容易理解的更小的问题是相对应的,这些较小的问题具有更好的边界(目标和接口)定义。**
|
||||
|
||||
网络分层的另一个主要目的是为了实现可替换性(interchangeability)。这意味着在一个网络中的一个层次的组件可以被替换为不同厂家的实现,只要它们遵循相同的标准和接口规范,不至于被卡脖子。
|
||||
|
||||
我想到了计算机世界非常非常有名的一句话,这里分享一下:
|
||||
|
||||
> 计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决,计算机整个体系从上到下都是按照严格的层次结构设计的。
|
||||
@ -262,7 +264,7 @@ PING 命令的输出结果通常包括以下几部分信息:
|
||||
3. **往返时间(RTT,Round-Trip Time)**:从发送 ICMP Echo Request(请求报文)到接收到 ICMP Echo Reply(响应报文)的总时间,用来衡量网络连接的延迟。
|
||||
4. **统计结果(Statistics)**:包括发送的 ICMP 请求数据包数量、接收到的 ICMP 响应数据包数量、丢包率、往返时间(RTT)的最小、平均、最大和标准偏差值。
|
||||
|
||||
如果 PING 对应的目标主机无法得到正确的响应,则表明这两个主机之间的连通性存在问题。如果往返时间(RTT)过高,则表明网络延迟过高。
|
||||
如果 PING 对应的目标主机无法得到正确的响应,则表明这两个主机之间的连通性存在问题(有些主机或网络管理员可能禁用了对ICMP请求的回复,这样也会导致无法得到正确的响应)。如果往返时间(RTT)过高,则表明网络延迟过高。
|
||||
|
||||
### PING 命令的工作原理是什么?
|
||||
|
||||
@ -286,9 +288,9 @@ DNS(Domain Name System)域名管理系统,是当用户使用浏览器访
|
||||
|
||||

|
||||
|
||||
在实际使用中,有一种情况下,浏览器是可以不必动用 DNS 就可以获知域名和 IP 地址的映射的。浏览器在本地会维护一个`hosts`列表,一般来说浏览器要先查看要访问的域名是否在`hosts`列表中,如果有的话,直接提取对应的 IP 地址记录,就好了。如果本地`hosts`列表内没有域名-IP 对应记录的话,那么 DNS 就闪亮登场了。
|
||||
在一台电脑上,可能存在浏览器 DNS 缓存,操作系统 DNS 缓存,路由器 DNS 缓存。如果以上缓存都查询不到,那么 DNS 就闪亮登场了。
|
||||
|
||||
目前 DNS 的设计采用的是分布式、层次数据库结构,**DNS 是应用层协议,基于 UDP 协议之上,端口为 53** 。
|
||||
目前 DNS 的设计采用的是分布式、层次数据库结构,**DNS 是应用层协议,它可以在UDP或TCP协议之上运行,端口为 53** 。
|
||||
|
||||
### DNS 服务器有哪些?
|
||||
|
||||
|
@ -489,8 +489,8 @@ value1
|
||||
| -------------------------------- | ------------------------------------------------- |
|
||||
| String | 一种二进制安全的数据结构,可以用来存储任何类型的数据比如字符串、整数、浮点数、图片(图片的 base64 编码或者解码或者图片的路径)、序列化后的对象。 |
|
||||
| List | Redis 的 List 的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。 |
|
||||
| Set | 一个 String 类型的 field-value(键值对) 的映射表,特别适合用于存储对象,后续操作的时候,你可以直接修改这个对象中的某些字段的值。 |
|
||||
| Hash | 无序集合,集合中的元素没有先后顺序但都唯一,有点类似于 Java 中的 `HashSet` 。 |
|
||||
| Hash | 一个 String 类型的 field-value(键值对) 的映射表,特别适合用于存储对象,后续操作的时候,你可以直接修改这个对象中的某些字段的值。 |
|
||||
| Set | 无序集合,集合中的元素没有先后顺序但都唯一,有点类似于 Java 中的 `HashSet` 。 |
|
||||
| Zset | 和 Set 相比,Sorted Set 增加了一个权重参数 `score`,使得集合中的元素能够按 `score` 进行有序排列,还可以通过 `score` 的范围来获取元素的列表。有点像是 Java 中 `HashMap` 和 `TreeSet` 的结合体。 |
|
||||
|
||||
## 参考
|
||||
|
@ -67,6 +67,8 @@ title: JavaGuide(Java学习&面试指南)
|
||||
- [LinkedHashMap 核心源码分析](./java/collection/linkedhashmap-source-code.md)
|
||||
- [CopyOnWriteArrayList 核心源码分析](./java/collection/copyonwritearraylist-source-code.md)
|
||||
- [ArrayBlockingQueue 核心源码分析](./java/collection/arrayblockingqueue-source-code.md)
|
||||
- [PriorityQueue 核心源码分析](./java/collection/priorityqueue-source-code.md)
|
||||
- [DelayQueue 核心源码分析](./java/collection/priorityqueue-source-code.md)
|
||||
|
||||
### IO
|
||||
|
||||
|
@ -1,4 +1,9 @@
|
||||
# Java8 新特性实战
|
||||
---
|
||||
title: Java8 新特性实战
|
||||
category: Java
|
||||
tag:
|
||||
- Java新特性
|
||||
---
|
||||
|
||||
> 本文来自[cowbi](https://github.com/cowbi)的投稿~
|
||||
|
||||
@ -602,60 +607,89 @@ public static <T> T requireNonNull(T obj) {
|
||||
|
||||
`ofNullable` 方法和`of`方法唯一区别就是当 value 为 null 时,`ofNullable` 返回的是`EMPTY`,of 会抛出 `NullPointerException` 异常。如果需要把 `NullPointerException` 暴漏出来就用 `of`,否则就用 `ofNullable`。
|
||||
|
||||
### `map()`相关方法。
|
||||
|
||||
```java
|
||||
/**
|
||||
* 如果value为null,返回EMPTY,否则返回Optional封装的参数值
|
||||
*/
|
||||
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
|
||||
Objects.requireNonNull(mapper);
|
||||
if (!isPresent())
|
||||
return empty();
|
||||
else {
|
||||
return Optional.ofNullable(mapper.apply(value));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 如果value为null,返回EMPTY,否则返回Optional封装的参数值,如果参数值返回null会抛 NullPointerException
|
||||
*/
|
||||
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
|
||||
Objects.requireNonNull(mapper);
|
||||
if (!isPresent())
|
||||
return empty();
|
||||
else {
|
||||
return Objects.requireNonNull(mapper.apply(value));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**`map()` 和 `flatMap()` 有什么区别的?**
|
||||
|
||||
**1.参数不一样,`map` 的参数上面看到过,`flatMap` 的参数是这样**
|
||||
`map` 和 `flatMap` 都是将一个函数应用于集合中的每个元素,但不同的是`map`返回一个新的集合,`flatMap`是将每个元素都映射为一个集合,最后再将这个集合展平。
|
||||
|
||||
在实际应用场景中,如果`map`返回的是数组,那么最后得到的是一个二维数组,使用`flatMap`就是为了将这个二维数组展平变成一个一维数组。
|
||||
|
||||
```java
|
||||
class ZooFlat {
|
||||
private DogFlat dog = new DogFlat();
|
||||
public class MapAndFlatMapExample {
|
||||
public static void main(String[] args) {
|
||||
List<String[]> listOfArrays = Arrays.asList(
|
||||
new String[]{"apple", "banana", "cherry"},
|
||||
new String[]{"orange", "grape", "pear"},
|
||||
new String[]{"kiwi", "melon", "pineapple"}
|
||||
);
|
||||
|
||||
public DogFlat getDog() {
|
||||
return dog;
|
||||
}
|
||||
List<String[]> mapResult = listOfArrays.stream()
|
||||
.map(array -> Arrays.stream(array).map(String::toUpperCase).toArray(String[]::new))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
System.out.println("Using map:");
|
||||
System.out.println(mapResult);
|
||||
|
||||
List<String> flatMapResult = listOfArrays.stream()
|
||||
.flatMap(array -> Arrays.stream(array).map(String::toUpperCase))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
System.out.println("Using flatMap:");
|
||||
System.out.println(flatMapResult);
|
||||
}
|
||||
|
||||
class DogFlat {
|
||||
private int age = 1;
|
||||
public Optional<Integer> getAge() {
|
||||
return Optional.ofNullable(age);
|
||||
}
|
||||
}
|
||||
|
||||
ZooFlat zooFlat = new ZooFlat();
|
||||
Optional.ofNullable(zooFlat).map(o -> o.getDog()).flatMap(d -> d.getAge()).ifPresent(age ->
|
||||
System.out.println(age)
|
||||
);
|
||||
```
|
||||
|
||||
**2.`flatMap()` 参数返回值如果是 null 会抛 `NullPointerException`,而 `map()` 返回`EMPTY`。**
|
||||
运行结果:
|
||||
|
||||
```
|
||||
Using map:
|
||||
[[APPLE, BANANA, CHERRY], [ORANGE, GRAPE, PEAR], [KIWI, MELON, PINEAPPLE]]
|
||||
|
||||
Using flatMap:
|
||||
[APPLE, BANANA, CHERRY, ORANGE, GRAPE, PEAR, KIWI, MELON, PINEAPPLE]
|
||||
```
|
||||
|
||||
最简单的理解就是`flatMap()`可以将`map()`的结果展开。
|
||||
|
||||
在`Optional`里面,当使用`map()`时,如果映射函数返回的是一个普通值,它会将这个值包装在一个新的`Optional`中。而使用`flatMap`时,如果映射函数返回的是一个`Optional`,它会将这个返回的`Optional`展平,不再包装成嵌套的`Optional`。
|
||||
|
||||
下面是一个对比的示例代码:
|
||||
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
int userId = 1;
|
||||
|
||||
// 使用flatMap的代码
|
||||
String cityUsingFlatMap = getUserById(userId)
|
||||
.flatMap(OptionalExample::getAddressByUser)
|
||||
.map(Address::getCity)
|
||||
.orElse("Unknown");
|
||||
|
||||
System.out.println("User's city using flatMap: " + cityUsingFlatMap);
|
||||
|
||||
// 不使用flatMap的代码
|
||||
Optional<Optional<Address>> optionalAddress = getUserById(userId)
|
||||
.map(OptionalExample::getAddressByUser);
|
||||
|
||||
String cityWithoutFlatMap;
|
||||
if (optionalAddress.isPresent()) {
|
||||
Optional<Address> addressOptional = optionalAddress.get();
|
||||
if (addressOptional.isPresent()) {
|
||||
Address address = addressOptional.get();
|
||||
cityWithoutFlatMap = address.getCity();
|
||||
} else {
|
||||
cityWithoutFlatMap = "Unknown";
|
||||
}
|
||||
} else {
|
||||
cityWithoutFlatMap = "Unknown";
|
||||
}
|
||||
|
||||
System.out.println("User's city without flatMap: " + cityWithoutFlatMap);
|
||||
}
|
||||
```
|
||||
|
||||
在`Stream`和`Optional`中正确使用`flatMap`可以减少很多不必要的代码。
|
||||
|
||||
### 判断 value 是否为 null
|
||||
|
||||
@ -733,7 +767,7 @@ public Optional<T> filter(Predicate<? super T> predicate) {
|
||||
|
||||
### 小结
|
||||
|
||||
看完 `Optional` 源码,`Optional` 的方法真的非常简单,值得注意的是如果坚决不想看见 `NPE`,就不要用 `of() `、 `get()`、`flatMap(..)`。最后再综合用一下 `Optional` 的高频方法。
|
||||
看完 `Optional` 源码,`Optional` 的方法真的非常简单,值得注意的是如果坚决不想看见 `NPE`,就不要用 `of()`、 `get()`、`flatMap(..)`。最后再综合用一下 `Optional` 的高频方法。
|
||||
|
||||
```java
|
||||
Optional.ofNullable(zoo).map(o -> o.getDog()).map(d -> d.getAge()).filter(v->v==1).orElse(3);
|
||||
@ -976,7 +1010,7 @@ System.out.println(date);
|
||||
//Wed Jan 27 14:05:29 CST 2021
|
||||
```
|
||||
|
||||
在新特性中引入了 `java.time.ZonedDateTime ` 来表示带时区的时间。它可以看成是 `LocalDateTime + ZoneId`。
|
||||
在新特性中引入了 `java.time.ZonedDateTime` 来表示带时区的时间。它可以看成是 `LocalDateTime + ZoneId`。
|
||||
|
||||
```java
|
||||
//当前时区时间
|
||||
|
Loading…
x
Reference in New Issue
Block a user