Java 8 Collectors toMap

Java 8 Collectors toMap

在使用Java stream的时候,会有需要将stream转换为Map的需求。

数据结构

下面的例子都会以图书信息作为实体。

public class Book {
    private String name;
    private Year releaseYear;
    private String isbn;

    // getters and setters
}

准备数据

List<Book> bookList = new ArrayList<>();
bookList.add(new Book("计算机程序的构造和解释", Year.of(2004), "9787111135104"));
bookList.add(new Book("算法导论", Year.of(2012), "9787111407010"));
bookList.add(new Book("计算机组成原理", Year.of(2017), "9787111558071"));
bookList.add(new Book("编译原理", Year.of(2008), "9787111251217"));
bookList.add(new Book("C程序设计语言(第2版·新版)", Year.of(2004), "9787111128069"));

toMaps

以ISBN作为key,以book作为value

bookList.stream().collect(Collectors.toMap(Book::getIsbn, Function.identity()))

以ISBN作为Key, 以书名作为value

bookList.stream().collect(Collectors.toMap(Book::getIsbn, Book::getName));

以年份为Key,统一年的书构建为一个list作为值

bookList.stream().collect(Collectors.toMap(
    Book::getReleaseYear,
    book -> {
        List<Book> books = new ArrayList<>();
        books.add(book)
        return books;
    },
    (prev, curr) -> {
        prev.addAll(curr);
        return prev;
    }
))

跨域

跨域设置

Access-Control-Allow-Credentials

Access-Control-Allow-Credentials 响应头用于在请求要求包含 credentials(Request.credentials 的值为 include)时,告知浏览器是否可以将对请求的响应暴露给前端 JavaScript 代码。

当请求的 credentials 模式(Request.credentials)为 include 时,浏览器仅在响应标头 Access-Control-Allow-Credentials 的值为 true 的情况下将响应暴露给前端的 JavaScript 代码。

Credentials 可以是 cookies、authorization headers 或 TLS client certificates。

当作为对预检请求的响应的一部分时,这能表示是否真正的请求可以使用 credentials。注意简单的GET 请求没有预检,所以若一个对资源的请求带了 credentials,如果这个响应头没有随资源返回,响应就会被浏览器忽视,不会返回到 web 内容。

Access-Control-Allow-Credentials 标头需要与 XMLHttpRequest.withCredentials 或 Fetch API 的 Request() 构造函数中的 credentials 选项结合使用。Credentials 必须在前后端都被配置(即 Access-Control-Allow-Credentials header 和 XHR 或 Fetch request 中都要配置)才能使带 credentials 的 CORS 请求成功。

语法

Access-Control-Allow-Credentials: true

指令

true: 这个头的唯一有效值(区分大小写)。如果不需要 credentials,相比将其设为 false,请直接忽视这个头。

Access-Control-Allow-Headers

响应首部 Access-Control-Allow-Headers 用于 preflight request(预检请求)中,列出了将会在正式请求的 Access-Control-Request-Headers 字段中出现的首部信息。

简单首部,如 simple headers、Accept、Accept-Language、Content-Language、Content-Type(只限于解析后的值为 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 三种 MIME 类型(不包括参数)),它们始终是被支持的,不需要在这个首部特意列出。

如果请求中含有 Access-Control-Request-Headers 字段,那么这个首部是必要的。

语法

Access-Control-Allow-Headers: <header-name>[, <header-name>]*
Access-Control-Allow-Headers: *

指令

<header-name>: 可支持的请求首部名字。请求头会列出所有支持的首部列表,用逗号隔开。

注意以下这些特定的首部是一直允许的:Accept, Accept-Language, Content-Language, Content-Type(但只在其值属于 MIME 类型 application/x-www-form-urlencoded, multipart/form-datatext/plain中的一种时)。这些被称作simple headers,你无需特意声明它们。

* (wildcard)

对于没有凭据的请求(没有 HTTP cookie 或 HTTP 认证信息的请求),值“*”仅作为特殊的通配符值。在具有凭据的请求中,它被视为没有特殊语义的文字标头名称“*”。请注意,Authorization标头不能使用通配符,并且始终需要明确列出。

Access-Control-Allow-Methods

响应首部 Access-Control-Allow-Methods 在对 preflight request.(预检请求)的应答中明确了客户端所要访问的资源允许使用的方法或方法列表。

语法

Access-Control-Allow-Methods: <method>, <method>, ...

指令

<method>: 用逗号隔开的允许使用的 HTTP request methods 列表。

  • GET: GET 方法请求一个指定资源的表示形式,使用 GET 的请求应该只被用于获取数据。
  • HEAD: HEAD 方法请求一个与 GET 请求的响应相同的响应,但没有响应体。
  • POST: POST 方法用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用。
  • PUT: PUT 方法用请求有效载荷替换目标资源的所有当前表示。
  • DELETE: DELETE 方法删除指定的资源。
  • CONNECT: CONNECT 方法建立一个到由目标资源标识的服务器的隧道。
  • OPTIONS: OPTIONS 方法用于描述目标资源的通信选项。
  • TRACE: TRACE 方法沿着到目标资源的路径执行一个消息环回测试。
  • PATCH: PATCH 方法用于对资源应用部分修改。

Access-Control-Allow-Origin

Access-Control-Allow-Origin 响应标头指定了该响应的资源是否被允许与给定的来源(origin)共享。

语法

Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>
Access-Control-Allow-Origin: null

Nginx配置

set $cors_origin '';
if ($http_origin ~* "lavecoral.me$") {
    set $cors_origin '$http_origin';
}

add_header Access-Control-Allow-Origin '$cors_origin';
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods 'GET, PUT, DELETE, PATCH, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'Authorization,X-Requested-With';

if ($request_method = 'OPTIONS') {
    return 204;
}

Mac brew安装MySQL8.0.28后忘记密码

跳过mysql的密码验证,修改配置文件my.cnf

在 MySQL 配置文件 /usr/local/etc/my.cnf 追加

skip-grant-tables

重启服务

重启 MySQL 服务,使得配置生效

mysql.server restart

修改密码

进入 MySQL

mysql -u root -p

输入密码时,直接回车.

修改密码

mysql> flush privileges;
mysql> use mysql;
mysql> alter user'root'@'localhost' IDENTIFIED BY 'Demo@123';

恢复 MySQL 配置文件

按照第一步操作将 skip-grant-tables删除或注释

重启mysql 登录测试

$ mysql.server restart

# 此时在登录就需要密码了
$ mysql -u root -p

ts-node直接运行typescript文件

正常ts文件都要编译成JS文件才能运行,但是在开发时有时需要运行ts文件,但是每次都要配置package.json,还要安装,后来看到ts-node可以在vscode上运行ts文件。

安装环境

//全局安装typescript和ts-node
npm install -g typescript
//npm install -g typescript-node 由于typescript-node不支持更高版本的ts
npm install -g ts-node //typescript@>=2.7

安装完成后就可以不用手动去编译成js文件,可以直接运行ts文件

//foo.ts
let foo = {
  baz: {
    a: 1
  }
}
console.log(foo);

执行命令ts-node **.ts

$ ts-node foo.ts
{ baz: { a: 1 } }

git代码统计

git代码统计

命令行

查看git上的个人代码量:

git log --author="username" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -

结果示例:(记得修改 username)

added lines: 120745, removed lines: 71738, total lines: 49007

统计每个人增删行数

git log --format='%aN' | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -; done

查看仓库提交者排名前 5

git log --pretty='%aN' | sort | uniq -c | sort -k1 -n -r | head -n 5

贡献值统计

git log --pretty='%aN' | sort -u | wc -l

提交数统计

git log --oneline | wc -l

添加或修改的代码行数:

git log --stat|perl -ne 'END { print $c } $c += $1 if /(\d+) insertions/'