2020年11月28日星期六

掌握JS模块化开发,编写高可用代码

开发一个模块管理引擎:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <script>  //AMD require.js  // CMD sea.js  //COMMONJS Node.js  //UMD  let module = (function () {   const moduleList = {};   function define(name, modules, action) {    modules.map((m, i) => {     modules[i] = moduleList[m]; //获取到依赖的方法    });    moduleList[name] = action.apply(null, modules);    // console.log(moduleList);   }   return { define };  })();  module.define('arr', [], function () {   console.log('define');   return {    first(arr) {     return arr[0];    },    max(arr, key) {     return arr.sort((a, b) => b[key] - a[key])[0];    }   }  });  module.define('lesson', ['arr'], function (arr) {   let data = [    { name: 'html', price: 199 },    { name: 'css', price: 265 },   ];   // console.log(arr);   console.log(arr.max(data, 'price'));  });  module.define('a', [], function () {   return {    name: 'cyy',    age: 18   }  });  module.define('b', ['a'], function (a) {   a.name = 'cyy2';  });  module.define('c', ['a'], function (a) {   console.log(a);  }); </script></body></html>

 

模块的基本使用:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <script type="module">  //引入时当前路径的./不可省略  import { name, age, show } from './script.js';  console.log(name, age);  show(); </script></body></html>

script.js

let name = 'cyy';let age = 18;function show() { console.log('show');}export { name, age, show };

 

模块延迟解析与严格模式:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <!-- 模块会在最后执行,此时元素已经渲染完毕 --> <!-- 使用type="module"时,默认是严格模式 --> <script type="module">  let div0 = document.querySelector('div');  console.log(div0); </script> <!-- 普通js必须在元素渲染之后使用 --> <script>  let div = document.querySelector('div');  console.log(div); </script> <div>cyy</div> <script>  let div2 = document.querySelector('div');  console.log(div2); </script></body></html>

 

作用域在模块中的体现:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <!-- 普通脚本在全局顶级作用域里 --> <script>  let url = 'www.baicu.com';  console.log(url); </script> <!-- module在自己的块级作用域里可以访问顶级作用域的内容但是顶级作用域里的内容不能访问到module里面的 --> <!-- 想要使用module里的内容,必须要通过导入和导出 --> <script type="module">  // console.log(url);  let cyy = 'cyy';  export { cyy }; </script> <script>  console.log(url); </script></body></html>

 

预解析的必要性:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <!-- 多次重复导入时会报错 --> <script type="module">  import { name, age } from './script.js';  import { name, age } from './script.js';  import { name, age } from './script.js';  console.log(name); </script></body></html>

 

模块的具名导出与导入:

// export let name = 'cyy';// export function show() { console.log('show') }// export class User {//  static func() {//   console.log('User-static-func');//  }// }// 具名导出// 批量导出let name = 'cyy';function show() { console.log('show') }class User { static func() {  console.log('User-static-func'); }}export { name, show, User };

 

批量导入与建议:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <!-- 具名导入 --> <script type="module">  // 批量导入并设置别名  import * as api from './script.js';  console.log(api.name);  api.show();  api.User.func(); </script></body></html>

 

别名使用:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <!-- 具名导入 --> <script type="module">  // 给导入的模块设置别名  import { name as n, s } from './script.js';  let name = 'cyy2';  console.log(n);  console.log(name);  s(); </script></body></html>

script.js

// 批量导出let name = 'cyy';function show() { console.log('show') }class User { static func() {  console.log('User-static-func'); }}// 导出也可以设置别名export { name, show as s, User };

 

default默认导出:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <!-- 具名导入 --> <script type="module">  // 默认导出的模块,导入时随便起什么名字都可以  // import myModule from './script.js';  // myModule.func();  import myModule from './script.js';  myModule.func(); </script></body></html>

script.js

// 当模块只有一个功能时,可以设置默认导出// 默认导出1// export default class User {//  static func() {//   console.log('User-static-func');//  }// }// 默认导出2class User { static func() {  console.log('User-static-func'); }}export { User as default };

 

混合导入导出的使用:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <!-- 具名导入 --> <script type="module">  // 具名导出的需要花括号,默认导出的不需要花括号  // import myModule, { show } from './script.js';  // myModule.func();  // show();  import * as api from './script.js';  console.log(api); </script></body></html>

script.js

// export default class User {//  static func() {//   console.log('User-static-func');//  }// }// export function show() {//  console.log('show');// }class User { static func() {  console.log('User-static-func'); }}function show() { console.log('show');}export { User as default, show };

 

默认导出模块的使用规范:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <!-- 具名导入 --> <script type="module">  // 默认导出的模块建议跟文件名同名,这样比较规范  import script from './script.js';  script.func(); </script></body></html>

 

模块的合并导出:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <script type="module">  import * as api from './index.js';  console.log(api); </script></body></html>

index.js

import * as script from './script.js';import * as script2 from './script2.js';export { script, script2 };

script.js

export default class User { static func() {  console.log('User-static-func'); }}

script2.js

let name = 'cyy';function show() { console.log('show');}export { name, show };

 

按需动态加载模块:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <style> </style></head><body> <button>click me</button> <script type="module">  // document.querySelector('button').addEventListener('click', function () {  //  //点击按钮之后按需加载模块  //  import('./script.js').then(module => {  //   console.log(module);  //  })  // });  document.querySelector('button').addEventListener('click', function () {   //点击按钮之后按需加载模块   import('./script2.js').then(({ name, show }) => {    console.log(name);    show();   })  }); </script></body></html>

script2.js

let name = 'cyy';function show() { console.log('show');}export { name, show };

 

WEBPACK构建项目的软件安装:

webpack打包工具,安装之前先安装node.js

使用一下命令生成配置文件package.json

npm init -y

 

安装webpack工具包,如果安装慢可以使用淘宝 cnpm (opens new window)命令

cnpm i webpack webpack-cli --save-dev

 

修改package.json添加打包命令,实时查看更新后的效果

..."main": "index.js","scripts": { "dev": "webpack --mode development --watch"},...

 

目录结构

index.html--dist #压缩打包后的文件--src----index.js #入口----style.js //模块

 

index.html内容如下

<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <script src="dist/main.js"></script> </body></html>

 

index.js内容如下

import style from "./style";new style().init();

 

style.js

export default class Style { constructor() { } init() {  document.body.style.backgroundColor = 'pink'; }}

 

执行打包

运行以下命令将生成打包文件到 dist目录,因为在命令中添加了 --watch参数,所以源文件编辑后自动生成打包文件。

npm run dev

 

可以看到html页面背景已经变成了粉色~









原文转载:http://www.shaoqun.com/a/493309.html

洋老板:https://www.ikjzd.com/w/2779

盘古集团:https://www.ikjzd.com/w/1448

吉祥邮:https://www.ikjzd.com/w/1565


开发一个模块管理引擎:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"
google correlate:google correlate
雨果网:雨果网
亚马逊品牌备案介绍、优势、注册流程:亚马逊品牌备案介绍、优势、注册流程
中山市仙踪龙园清明节活动介绍?清明节去中山仙踪龙园好玩吗?:中山市仙踪龙园清明节活动介绍?清明节去中山仙踪龙园好玩吗?
请问惠州淡水到深圳蛇口座车要多久?:请问惠州淡水到深圳蛇口座车要多久?

《逆袭之偷心千金》在象山影视城开机,开启甜爱偶像剧集新时代

原标题:《逆袭之偷心千金》在象山影视城开机,开启甜爱偶像剧集新时代

由王天楚担任总制片人、总编剧、导演,叶田担任总导演的剧集《逆袭之偷心千金》11月27日在 象山影视城举行了开机仪式,导演携主演郑湫泓、李明峻、余凯宁、子剑、张乔耳、叶舒予、朱云龙、米良、吴恒等一众主创出席了仪式。

▲象山影视城剧组开机现场

剧集《逆袭之偷心千金》的原IP《偷心魔女》在橙光游戏站内一直享有非常高的热度,其娱乐圈话题、玛丽苏类型及甜宠争斗的元素也虏获了众多粉丝的一致好评。作为拥有优秀IP数据支撑的作品,《逆袭之偷心千金》在观众沉浸式的剧情体验方面下足了功夫,在原剧情的基础上增加了许多新鲜的元素,极大丰富了观影过程中的养成感和代入感。

剧集《逆袭之偷心千金》描述了一个十八线不知名的女明星,如何在职场中一步步升级变强最终成为一个有名气、有能力的好演员的成长之路,既有跌宕起伏的剧情作为支撑,更有明星、女性、逆袭、甜宠等众多的话题性元素集合。千金系列作品《绝世千金》分账票房金额超过8800万,作为现代版新作《逆袭之偷心千金》在延续好内容的同时,制作上全面升级,将为观众带来更加精彩的观影体验。

据悉,剧集《逆袭之偷心千金》由酷影传媒、东仑传媒、耐飞影视出品,善为影业联合出品,酷影传媒承制,东仑传媒联合承制,耐飞影视独家发行,现已进入紧张的拍摄阶段,更多精彩内容,敬请期待。

(文中部分图片和文字来源网络,如有侵权请及时联系删除)返回搜狐,查看更多

责任编辑:

原文转载:http://yl.shaoqun.com/a/208964.html

extra:https://www.ikjzd.com/w/1736

铭宣:https://www.ikjzd.com/w/1551.html

mav:https://www.ikjzd.com/w/2414


原标题:《逆袭之偷心千金》在象山影视城开机,开启甜爱偶像剧集新时代由王天楚担任总制片人、总编剧、导演,叶田担任总导演的剧集《逆袭之偷心千金》11月27日在象山影视城举行了开机仪式,导演携主演郑湫泓、李明峻、余凯宁、子剑、张乔耳、叶舒予、朱云龙、米良、吴恒等一众主创出席了仪式。▲象山影视城剧组开机现场剧集《逆袭之偷心千金》的原IP《偷心魔女》在橙光游戏站内一直享有非常高的热度,其娱乐圈话题、玛丽苏类
csa:csa
蜜芽宝贝:蜜芽宝贝
四川布拖大凉山下的彝族祭火人家 :四川布拖大凉山下的彝族祭火人家
亚马逊运营各个阶段可以用到的表格参考:亚马逊运营各个阶段可以用到的表格参考
aspnet 教程,vb.net教程,net教程下载,ado.net教程,net入门,c#.net教程:aspnet 教程,vb.net教程,net教程下载,ado.net教程,net入门,c#.net教程

GitHub 上 1.3k Star 的 strman-java 项目有值得学习的地方吗?源码视角

大家好,我是沉默王二。

很多初学编程的同学,经常给我吐槽,说:"二哥,你在敲代码的时候会不会有这样一种感觉,写着写着看不下去了,觉得自己写出来的代码就好像屎一样?"

这里我必须得说一句,初入"江湖"的时候,确实会觉得自己的代码写得很烂,但这么多年下来,这种感觉已经荡然无存了。

(吹嘛,我也会,哈哈)

那,怎么才能让写出来的代码不那么烂呢?

我的一个经验就是,"拿来主义",尽量不去重复造轮子。使用那些已经被验证过,足够优质的开源库不仅能够让我们的代码变得优雅,还能够让我们在不断的使用过程当中,学习到编程的精髓。

洋务运动的时候,有一句很响亮的口号叫做,"师夷长技以制夷"。先去用,再去学,自然而然就会变得牛逼。同学们,你们说,是不是这个理?

我今天推荐的这款开源库,名字叫做 strman-java,GitHub 上标星 1.3k,一款超赞的字符串处理工具库,基于 Java 8,语法非常简洁。

接下来,我们来看看怎么用。

Maven 项目只需要在 pom.

<dependency>
    <groupId>com.shekhargulati</groupId>
    <artifactId>strman</artifactId>
    <version>0.4.0</version>
</dependency>

好了,可以肆无忌惮地调用 strman-java 的 API 了。我会在介绍的时候插入一些源码的介绍,方便同学们更深一步的学习,尽量做到"知其然知其所以然"。

01、append

把可变字符串参数添加到指定的字符串尾部。

Strman.append("沉","默","王","二");

结果如下所示:

沉默王二

append 对应的方法是 prepend,把可变字符串参数前置到指定的字符串前面,使用方法如下。

Strman.prepend("沉","默","王","二");

结果如下所示:

默王二沉

02、appendArray

把字符串数组添加到指定的字符串尾部。

String [] strs = {"默","王","二"};
Strman.appendArray("沉",strs);

结果如下所示:

沉默王二

append 内部其实调用的 appendArray,来看一下源码:

public static String append(final String value, final String... appends) {
    return appendArray(value, appends);
}

当使用可变参数的时候,实际上是先创建了一个数组,该数组的大小就是可变参数的个数,然后将参数放入数组当中,再将数组传递给被调用的方法

通过观察反编译后的字节码,就能看得到。

Strman.append("沉","默","王","二");

实际等同于:

Strman.append("沉", new String[]{"默", "王", "二"});

再来看一下 appendArray 方法的源码:

public static String appendArray(final String value, final String[] appends) {
    StringJoiner joiner = new StringJoiner("");
    for (String append : appends) {
        joiner.add(append);
    }
    return value + joiner.toString();
}

内部用的 StringJoiner,Java 8 时新增的一个类。构造方法有两种。

第一种,指定分隔符:

public StringJoiner(CharSequence delimiter) {
    this(delimiter, "", "");
}

第二种,指定分隔符、前缀、后缀:

public StringJoiner(CharSequence delimiter,
                    CharSequence prefix,
                    CharSequence suffix) {
    this.prefix = prefix.toString();
    this.delimiter = delimiter.toString();
    this.suffix = suffix.toString();
}

虽然也可以在 StringBuilder 类的帮助下在每个字符串之后附加分隔符,但 StringJoiner 提供了更简单的方法来实现,无需编写大量的代码。

03、at

获取指定索引处上的字符。

Strman.at("沉默王二", 0);
Strman.at("沉默王二", -1);
Strman.at("沉默王二", 4);

结果如下所示:

Optional[沉]
Optional[二]
Optional.empty

也就是说,at 可以处理 -(length-1)(length-1) 之内的索引(当索引为负数的时候将从末尾开始查找),如果超出这个范围,将会返回 Optional.empty,避免发生空指针。

来看一下源码:

public static Optional<String> at(final String value, int index) {
    if (isNullOrEmpty(value)) {
        return Optional.empty();
    }
    int length = value.length();
    if (index < 0) {
        index = length + index;
    }
    return (index < length && index >= 0) ? Optional.of(String.valueOf(value.charAt(index))) : Optional.empty();
}

本质上,是通过 String 类的 charAt() 方法查找的,但包裹了一层 Optional,就巧妙地躲开了烦人的空指针。

Optional 是 Java 8 时新增的一个类,该类提供了一种用于表示可选值而非空引用的类级别解决方案。

04、between

按照指定起始字符和截止字符来返回一个字符串数组。

String [] results = Strman.between("[沉默王二][一枚有趣的程序员]","[", "]");
System.out.println(Arrays.toString(results));

结果如下所示:

[沉默王二, 一枚有趣的程序员]

来看一下源码:

public static String[] between(final String value, final String start, final String end) {
    String[] parts = value.split(end);
    return Arrays.stream(parts).map(subPart -> subPart.substring(subPart.indexOf(start) + start.length()))
            .toArray(String[]::new);
}

java.util.Arrays 类是为数组而生的专用工具类,基本上常见的对数组的操作,Arrays 类都考虑到了,stream() 方法可以将数组转换成流:

String[] intro = new String[] { "沉", "默", "王", "二" };
Arrays.stream(intro);

Java 8 新增的 Stream 流在很大程度上提高了开发人员在操作集合(Collection)时的生产力。要想操作流,首先需要有一个数据源,可以是数组或者集合。每次操作都会返回一个新的流对象,方便进行链式操作,但原有的流对象会保持不变。

map() 方法可以把一个流中的元素转化成一个新流中的元素,它可以接收一个 Lambda 表达式作为参数。Lambda 表达式描述了一个代码块(或者叫匿名方法),可以将其作为参数传递给构造方法或者普通方法以便后续执行。

考虑下面这段代码:

() -> System.out.println("沉默王二")

来从左到右解释一下,() 为 Lambda 表达式的参数列表(本例中没有参数),-> 标识这串代码为 Lambda 表达式(也就是说,看到 -> 就知道这是 Lambda),System.out.println("沉默王二") 为要执行的代码,即将"沉默王二"打印到标准输出流。

toArray() 方法可以将流转换成数组,你可能比较好奇的是 String[]::new,它是什么东东呢?来看一下 toArray() 方法的源码。

<A> A[] toArray(IntFunction<A[]> generator);

也就是说 String[]::new 是一个 IntFunction,一个可以产生所需的新数组的函数,可以通过反编译字节码看看它到底是什么:

String[] strArray = (String[])list.stream().toArray((x$0) -> {
    return new String[x$0];
});

也就是相当于返回了一个指定长度的字符串数组。

05、chars

返回组成字符串的单个字符的数组。

String [] results = Strman.chars("沉默王二");
System.out.println(Arrays.toString(results));

结果如下所示:

[沉, 默, 王, 二]

来看一下源码:

public static String[] chars(final String value) {
    return value.split("");
}

内部是通过 String 类的 split() 方法实现的。

06、charsCount

统计字符串中每个字符出现的次数。

Map<Character, Long> map = Strman.charsCount("沉默王二的妹妹叫沉默王三");
System.out.println(map);

结果如下所示:

{的=1, 默=2, 三=1, 妹=2, 沉=2, 叫=1, 王=2, 二=1}

是不是瞬间觉得这个方法有意思多了,一步到位,统计出字符串中各个字符出现的次数,来看一下源码吧。

public static Map<Character, Long> charsCount(String input) {
    return input.chars().mapToObj(c -> (char) c).collect(groupingBy(identity(), counting()));
}

String 类的 chars() 方法是 Java 9 新增的,它返回一个针对基本类型 int 的流:IntStream。

mapToObj() 方法主要是将 Stream 中的元素进行装箱操作, 转换成一个引用类型的值, 它接收一个 IntFunction 接口, 它是一个 int -> R 的函数接口。

collect() 方法可以把流转成集合 Map。

07、collapseWhitespace

用单个空格替换掉多个连续的空格。

Strman.collapseWhitespace("沉默王二       一枚有趣的程序员");

结果如下所示:

Strman.collapseWhitespace("沉默王二       一枚有趣的程序员")

来看一下源码:

public static String collapseWhitespace(final String value) {
    return value.trim().replaceAll("\\s\\s+", " ");
}

内部先用 trim() 方法去掉两侧的空格,然后再用正则表达式将多个连续的空格替换成单个空格。

08、contains

验证指定的字符串是否包含某个字符串。

System.out.println(Strman.contains("沉默王二", "沉"));
System.out.println(Strman.contains("Abbc", "a", false));

结果如下所示:

true
true

第三个参数 caseSensitive 是可选项,如果为 false 则表明不区分大小写。

来看一下源码:

public static boolean contains(final String value, final String needle, final boolean caseSensitive) {
    if (caseSensitive) {
        return value.contains(needle);
    }
    return value.toLowerCase().contains(needle.toLowerCase());
}

内部通过 String 类的 contains() 方法实现,如果不区分大小写,则先调用 toLowerCase() 方法转成小写。

09、containsAny

验证指定的字符串是否包含字符串数组中任意一个字符串,或更多。

System.out.println(Strman.containsAny("沉默王二", new String [] {"沉","三"}));
System.out.println(Strman.containsAny("沉默王二", new String [] {"沉默","三"}));
System.out.println(Strman.containsAny("沉默王二", new String [] {"不","三"}));

结果如下所示:

true
true
false

来看一下源码:

public static boolean containsAny(final String value, final String[] needles, final boolean caseSensitive) {
    return Arrays.stream(needles).anyMatch(needle -> contains(value, needle, caseSensitive));
}

Stream 类提供了三个方法可供进行元素匹配,它们分别是:

  • anyMatch(),只要有一个元素匹配传入的条件,就返回 true。

  • allMatch(),只有有一个元素不匹配传入的条件,就返回 false;如果全部匹配,则返回 true。

  • noneMatch(),只要有一个元素匹配传入的条件,就返回 false;如果全部匹配,则返回 true。

10、endsWith

验证字符串是否以某个字符串结尾。

System.out.println(Strman.endsWith("沉默王二","二"));
System.out.println(Strman.endsWith("Abbc", "A", false));

结果如下所示:

true
false

来看一下源码:

public static boolean endsWith(final String value, final String search, final int position,
                               final boolean caseSensitive) {
    int remainingLength = position - search.length();
    if (caseSensitive) {
        return value.indexOf(search, remainingLength) > -1;
    }
    return value.toLowerCase().indexOf(search.toLowerCase(), remainingLength) > -1;
}

内部通过 String 类的 indexOf() 方法实现。

11、ensureLeft

确保字符串以某个字符串开头,如果该字符串没有以指定的字符串开头,则追加上去。

System.out.println(Strman.ensureLeft("沉默王二", "沉"));
System.out.println(Strman.ensureLeft("默王二", "沉"));

结果如下所示:

沉默王二
沉默王二

来看一下源码:

public static String ensureLeft(final String value, final String prefix, final boolean caseSensitive) {
    if (caseSensitive) {
        return value.startsWith(prefix) ? value : prefix + value;
    }
    String _value = value.toLowerCase();
    String _prefix = prefix.toLowerCase();
    return _value.startsWith(_prefix) ? value : prefix + value;
}

内部通过 String 类的 startsWith() 方法先进行判断,如果结果为 false,则通过"+"操作符进行连接。

ensureLeft 对应的还有 ensureRight,同理,这里不再赘述。

12、base64Encode

把字符串进行 base64 编码。

Strman.base64Encode("沉默王二");

结果如下所示:

5rKJ6buY546L5LqM

Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法。来看一下源码:

public static String base64Encode(final String value) {
    return Base64.getEncoder().encodeToString(value.getBytes(StandardCharsets.UTF_8));
}

内部是通过 Base64 类实现的,Java 8 新增的一个类。

base64Encode 对应的解码方法是 base64Decode,使用方法如下所示:

Strman.base64Decode("5rKJ6buY546L5LqM")

如果不可解码的会,会抛出 IllegalArgumentException 异常。

Exception in thread "main" java.lang.IllegalArgumentException: Last unit does not have enough valid bits
  at java.base/java.util.Base64$Decoder.decode0(Base64.java:763)
  at java.base/java.util.Base64$Decoder.decode(Base64.java:535)
  at java.base/java.util.Base64$Decoder.decode(Base64.java:558)
  at strman.Strman.base64Decode(Strman.java:328)
  at com.itwanger.strman.Demo.main(Demo.java:58)

13、binEncode

把字符串转成二进制的 Unicode(16 位)。

Strman.binEncode("沉默王二");

结果如下所示:

0110110010001001100111101101100001110011100010110100111010001100

binEncode 对应的方法是 binDecode,把二进制的 Unicode 转成字符串,使用方法如下所示:

Strman.binDecode("0110110010001001100111101101100001110011100010110100111010001100");

14、first

返回字符串的前 N 个字符。

System.out.println(Strman.first("沉默王二", 0));
System.out.println(Strman.first("沉默王二", 1));
System.out.println(Strman.first("沉默王二", 2));

结果如下所示:

Optional[]
Optional[沉]
Optional[沉默]

如果 N 为负数的话,将会抛出 StringIndexOutOfBoundsException 异常:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: begin 0, end -1, length 4
  at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3319)
  at java.base/java.lang.String.substring(String.java:1874)
  at strman.Strman.lambda$first$9(Strman.java:414)
  at java.base/java.util.Optional.map(Optional.java:265)
  at strman.Strman.first(Strman.java:414)
  at com.itwanger.strman.Demo.main(Demo.java:68)

针对 N 为负数的情况,我觉得没有之前的 at 方法处理的巧妙。

来看一下源码:

public static Optional<String> first(final String value, final int n) {
    return Optional.ofNullable(value).filter(v -> !v.isEmpty()).map(v -> v.substring(0, n));
}

内部是通过 String 类的 substring() 方法实现的,不过没有针对 n 小于 0 的情况做处理。

ofNullable() 方法可以创建一个即可空又可非空的 Optional 对象。

filter() 方法的参数类型为 Predicate(Java 8 新增的一个函数式接口),也就是说可以将一个 Lambda 表达式传递给该方法作为条件,如果表达式的结果为 false,则返回一个 EMPTY 的 Optional 对象,否则返回过滤后的 Optional 对象。

map() 方法可以按照一定的规则将原有 Optional 对象转换为一个新的 Optional 对象,原有的 Optional 对象不会更改。

first 对应的的是 last 方法,返回字符串的后 N 个字符。

15、head

返回字符串的第一个字符。

Strman.head("沉默王二");

结果如下所示:

Optional[沉]

来看一下源码:

public static Optional<String> head(final String value) {
    return first(value, 1);
}

内部是通过调用 first() 方法实现的,只不过 N 为 1。

16、unequal

检查两个字符串是否不等。

Strman.unequal("沉默王二","沉默王三");

结果如下所示:

true

来看一下源码:

public static boolean unequal(final String first, final String second) {
    return !Objects.equals(first, second);
}

内部是通过 Objects.equals() 方法进行判断的,由于 String 类重写了 equals() 方法,也就是说,实际上还是通过 String 类的 equals() 方法进行判断的。

17、insert

把字符串插入到指定索引处。

Strman.insert("沉默二","王",2);

结果如下所示:

沉默王二

来看一下源码:

public static String insert(final String value, final String substr, final int index) {
    if (index > value.length()) {
        return value;
    }
    return append(value.substring(0, index), substr, value.substring(index));
}

如果索引超出字符串长度,直接返回原字符串;否则调用 append() 方法将指定字符串插入到对应索引处。

18、repeat

对字符串重复指定次数。

Strman.repeat("沉默王二", 3);

结果如下所示:

沉默王二沉默王二沉默王二

来看一下源码:

public static String repeat(final String value, final int multiplier) {
    return Stream.generate(() -> value).limit(multiplier).collect(joining());
}

Stream.generate() 生成的 Stream,默认是串行(相对 parallel 而言)但无序的(相对 ordered 而言)。由于它是无限的,在管道中,必须利用 limit 之类的操作限制 Stream 大小。

collect(joining()) 可以将流转成字符串。

19、leftPad

返回给定长度的新字符串,以便填充字符串的开头。

Strman.leftPad("王二","沉默",6);

结果如下所示:

沉默沉默沉默沉默王二

来看一下源码:

public static String leftPad(final String value, final String pad, final int length) {
    if (value.length() > length) {
        return value;
    }
    return append(repeat(pad, length - value.length()), value);
}

内部会先调用 repeat() 方法进行补位,然后再调用 append() 方法拼接。

leftPad 方法对应的是 rightPad,填充字符串的末尾。

19)removeEmptyStrings,从字符串数组中移除空字符串。

String [] results = Strman.removeEmptyStrings(new String[]{"沉", " ", "   ", "默王二"});
System.out.println(Arrays.toString(results));

结果如下所示:

[沉, 默王二]

来看一下源码:

public static String[] removeEmptyStrings(String[] strings) {
    if (Objects.isNull(strings)) {
        throw new IllegalArgumentException("Input array should not be null");
    }
    return Arrays.stream(strings).filter(str -> str != null && !str.trim().isEmpty()).toArray(String[]::new);
}

通过 Stream 的 filter() 方法过滤掉了空格。

20、reverse

反转字符串。

Strman.reverse("沉默王二");

结果如下所示:

二王默沉

来看一下源码:

public static String reverse(final String value) {
    return new StringBuilder(value).reverse().toString();
}

内部是通过 StringBuilder 类的 reverse() 方法进行反转的。

21、safeTruncate

对字符串进行截断,但不会破坏单词的完整性。

Strman.safeTruncate("Java is the best",13,"...");

结果如下所示:

Java is...

来看一下源码:

public static String safeTruncate(final String value, final int length, final String filler) {
    if (length == 0) {
        return "";
    }
    if (length >= value.length()) {
        return value;
    }

    String[] words = words(value);
    StringJoiner result = new StringJoiner(" ");
    int spaceCount = 0;
    for (String word : words) {
        if (result.length() + word.length() + filler.length() + spaceCount > length) {
            break;
        } else {
            result.add(word);
            spaceCount++;
        }
    }
    return append(result.toString(), filler);
}

先调用 words() 方法对字符串进行单词分割,然后按照长度进行截断,最后调用 append() 方法填充上补位符。

safeTruncate 对应的是 truncate,可能会破坏单词的完整性,使用方法如下所示:

Strman.truncate("Java is the best",13,"...")

结果如下所示:

Java is th...

来看一下源码:

public static String truncate(final String value, final int length, final String filler) {
    if (length == 0) {
        return "";
    }
    if (length >= value.length()) {
        return value;
    }
    return append(value.substring(0, length - filler.length()), filler);
}

就是单纯的切割和补位,没有对单词进行保护。

22、shuffle

对字符串重新洗牌。

Strman.shuffle("沉默王二");

结果如下所示:

王默二沉

来看一下源码:

public static String shuffle(final String value) {
    String[] chars = chars(value);
    Random random = new Random();
    for (int i = 0; i < chars.length; i++) {
        int r = random.nextInt(chars.length);
        String tmp = chars[i];
        chars[i] = chars[r];
        chars[r] = tmp;
    }
    return Arrays.stream(chars).collect(joining());
}

调用 chars() 方法把字符串拆分为字符串数组,然后遍历对其重排,最后通过 Stream 转成新的字符串。

23、其他方法

Strman 中还有很多其他巧妙的字符串处理方法,比如说把字符串按照指定的前后缀进行包裹 surround 等等,同学们可以参考 Strman 的官方文档进行学习:

https://github.com/shekhargulati/strman-java/wiki

PS:最近有小伙伴私信我要一份优质的 Java 教程,我在 GitHub 花了很长时间才找到了一份,115k star,真的非常不错,来看一下目录:

花了三个半小时把这份教程整理成 PDF 后,我发给了小伙伴,他"啪"的一下就发过来了私信,很快啊,"二哥,你也太用心了,这份教程的质量真的高,不服不行!"

如果你也对这份 PDF 感兴趣的话,可以通过下面的方式获取。

链接:https://pan.baidu.com/s/1rT0l5ynzAQLF--efyRHzQw 密码:dz95

多说一句,遇到好的资源,在让它吃灰的同时,能学一点就赚一点,对吧?知识是无穷无尽的,但只要我们比其他人多学到了那么一点点,那是不是就超越了呢?

点个赞吧,希望更多的人看得到!










原文转载:http://www.shaoqun.com/a/493298.html

csa:https://www.ikjzd.com/w/904

史泰博办公用品:https://www.ikjzd.com/w/2112

贝贝官网:https://www.ikjzd.com/w/1321


大家好,我是沉默王二。很多初学编程的同学,经常给我吐槽,说:"二哥,你在敲代码的时候会不会有这样一种感觉,写着写着看不下去了,觉得自己写出来的代码就好像屎一样?"这里我必须得说一句,初入"江湖"的时候,确实会觉得自己的代码写得很烂,但这么多年下来,这种感觉已经荡然无存了。(吹嘛,我也会,哈哈)那,怎么才能让写出来的代码不那么烂呢?我的一个经验就是,"拿来主义",尽量不去重复造轮子。使用那些已经被验
易趣:易趣
国际标准书号:国际标准书号
万绿湖景区有什么美食?:万绿湖景区有什么美食?
退运服务全解密!eBay Return Helper有问必答!:退运服务全解密!eBay Return Helper有问必答!
肇庆有什么值得去看的旅游景点?:肇庆有什么值得去看的旅游景点?

日本网友好评中国漫改剧?太尴尬了…

原标题:日本网友好评中国漫改剧?太尴尬了…

最近,本i吃瓜群众小通百无聊赖刷微博之际,被一条明晃晃的热搜吸引了眼球。

em?日本网友上了中国热搜??这是怎么肥四?!

抱着吃瓜心态点进这条热搜,发现原来是有博主发文称,

改编自著名同名日漫的网剧《棋魂》在日本反响热烈,并贴出了一系列来自外网的评论,清一色都是好评。

改编作品受到肯定,好事啊!国产剧出息了!

可尴尬的是,随后有网友指出:

热搜话题中对《棋魂》高度称赞的"日本网友"并不是真正的日本人,

大多是中国人或是在日华人。

因为推文所用的 日语都比较"中式",转评赞也都在个位数。

说白了,所谓"日本网友好评如潮"可能只是部分人的自我感动罢了。

事情一经爆出,吃瓜群众也是议论纷纷,

想要得到观众认可的心理可以理解,

但是 这样掺了水的表扬,着实让人有些尴尬。

说起《棋魂》的原作本身,想必很多人都不会陌生。

《棋魂》的原著漫画,可以说是无数人的围棋启蒙。2001年动漫版播出后,更是引发中日韩全民学棋的热潮。要改编这样一部现象级日漫IP,可想而知难度有多大。

▲9.2分的动漫版想必是很多人的白月光了

那么剧版《棋魂》完成度如何呢?

其实,抛开前文的尴尬热搜,这部剧版《棋魂》质量算得上可圈可点。

豆瓣8.4的评分,不说一骑绝尘,起码在近年连连翻车的日剧翻拍里,可以算得上优秀选手。

许多网友真情实感的"真香体验"和"自来水"行为也说明了:真正的好作品,还是该让它用质量说话。

(据说结局崩坏,各位还是谨慎入坑)

话说近年来,日系作品本土化成绩是有目共睹的糟糕,

且不说引发全民吐槽的中国版 《深夜食堂》,其他诸如《 求婚大作战》《约会恋爱究竟是什么》《问题餐厅》等改编剧也纷纷折戟,口碑收视两不沾。

相比起来,改编自日剧《卖房子的女人》的 《安家》,虽然在孙俪的坐镇下收视有了保障,但口碑也是见仁见智。

日系作品的本土化改编难度可想而知。

众所周知,日系作品的改编剧最怕的就是"水土不服"。同样的事物放到不同的文化背景中去,观感可能就是天差地别。

最经典的翻车案例就是黄磊版 《深夜食堂》

直接东施效颦地将日本街头的居酒屋搬进上海弄堂,剧里经历996后的疲惫打工人不是选择回家躺尸,而是一个个妆发精致的坐等黄磊献上一盆老坛酸菜面,这剧情,怎么看都很悬浮。

同样照搬还有翻拍自同名日剧的 《求婚大作战》

水手服、棒球队、花火大会这些元素出现在日剧里合情合理,一旦被照葫芦画瓢的安插进国产剧中,只会让人觉得格格不入。

难怪有网友吐槽:我不知道这修正的是谁的青春,反正肯定不是我的。

天然的文化鸿沟不可避免,中日虽然是一衣带水的邻国,但两国从生活习惯到文化信仰都存在不小的差异, 要如何将作品改编得对国人口味又不失原作气韵,是对导演和编剧的巨大考验。

在8.4分的《棋魂》之前,也并不是没有出现过叫好又叫座的日漫改编剧,其中最经典的要数 《恶作剧之吻》

这部让无数90后高呼"爷青回"的偶像剧豆瓣评分高达8.9,比柏原崇的原版还高出0.4。

《恶吻》之所以成功,除了导演和演员把日常温馨有趣的细节演绎到了极致之外,在本土化方面也做得巧妙自然,让观众很容易忽略它本身是一部改编翻拍日剧的事实。

改编剧需要用心打磨,不是买了版权就能万事大吉的。

这几年,伴着中日文化交流的热潮,改编的日剧日影日漫层出不穷,似乎已成趋势。

除了已经官宣年底上映的由郭敬明导演,改编自梦枕貘原著小说的电影 《阴阳师之晴雅集》,还有 非自然死亡为了N最完美的离婚》《龙樱》《我的危险妻子》等经典日剧也被购买了版权将陆续翻拍。

不知道这些剧上线后又会收获怎样的口碑?

还会不会有"日本网友"关注?

就让我们一起坐等吃瓜吧~

小通荐书

点击下图购买

《骂观众》

彼得·汉德克 著

2019年诺贝尔文学奖获奖者作品

余华推荐!

德语文学"活着的经典"

藐视观众,藐视剧场的经典之作

如人刑室,如坐针毡

欲怒不生,欲走不能

点击图片阅读

转载请联系我们,获得授权返回搜狐,查看更多

责任编辑:

原文转载:http://yl.shaoqun.com/a/208938.html

易佰:https://www.ikjzd.com/w/1482

拍拍网服装:https://www.ikjzd.com/w/2205

haofang:https://www.ikjzd.com/w/1046


原标题:日本网友好评中国漫改剧?太尴尬了…最近,本i吃瓜群众小通百无聊赖刷微博之际,被一条明晃晃的热搜吸引了眼球。em?日本网友上了中国热搜??这是怎么肥四?!抱着吃瓜心态点进这条热搜,发现原来是有博主发文称,改编自著名同名日漫的网剧《棋魂》在日本反响热烈,并贴出了一系列来自外网的评论,清一色都是好评。改编作品受到肯定,好事啊!国产剧出息了!可尴尬的是,随后有网友指出:热搜话题中对《棋魂》高度称赞
myyearbook:myyearbook
淘粉8:淘粉8
第二届中国国际跨境电商发展高峰论坛召开,中外嘉宾畅谈如何实现跨境电商全球效益红利!:第二届中国国际跨境电商发展高峰论坛召开,中外嘉宾畅谈如何实现跨境电商全球效益红利!
蜀南竹海美食推荐—全竹宴 :蜀南竹海美食推荐—全竹宴
2020广东春节旅游去哪里?佛山春节旅游好玩的地方?:2020广东春节旅游去哪里?佛山春节旅游好玩的地方?

央视21年热剧片单!孙俪朱一龙刘诗诗倪妮肖战看好谁

原标题:央视21年热剧片单!孙俪朱一龙刘诗诗倪妮肖战看好谁

11月26日下午,"大剧看总台——中央广播电视总台2021年电视剧片单发布活动"在北京举行。

《跨过鸭绿江》《大决战》《红船》《热血珠峰》《城中之城》《天望》《人世间》等多部影视剧主创人员登场,现场还发布了一系列概念海报、定妆照、预告片等物料。

而《甜蜜》《生活万岁》《叛逆者》《危机先生》等剧的主创人员,也来到现场宣传新剧。

其中,《叛逆者》主演朱一龙、童瑶回顾片中拍摄细节,翩翩起舞,朱一龙还因紧张到踩到童瑶。

《叛逆者》主演:朱一龙、童瑶、王志文、朱珠

这部剧融合了战争、爱情、复仇等诸多元素,展示了中国革命人坚持信仰,不畏牺牲不屈精神。活动现场,朱一龙还特地为大家展示了剧中的拍摄道具,围绕剧中的老式相机讲述了角色斗智斗勇的经历。

朱一龙为大家透露了他所饰演角色林楠笙的人物设定,既有书生的沉稳,也有战士的热血,在经历了诸多磨难后,最终看清了未来的正确道路。

《理想之城》主演:孙俪、赵又廷、于和伟、陈明昊、杨超越

该剧改编自若花燃燃所著小说《苏筱的战争》,讲述了造价师苏筱的成长之路,并反映中国建筑行业现状。有孙俪、赵又廷、于和伟这些大腕合作,还是很值得期待。

《装台》主演:张嘉益、闫妮、宋丹丹、秦海璐、文章

该剧根据陈彦的同名小说改编,讲述了装台人的悲欢离合、酸甜苦辣,以及古城西安在改革开放大潮中的故事,追光平凡人物,上演烟火人生。张嘉益、闫妮、宋丹丹、秦海璐、文章等大腕合作,让人期待。

《甜蜜》主演:海清、任重、施诗

该剧讲述了都市女性田蜜由于丈夫自杀从一个养尊处优的富太太跌入生活谷底,不得不扛起替丈夫偿还债务的重担,后一路拼搏成长为一名金融理财师,并收获美满爱情的故事。海清、任重、施诗主演,还是不错阵容。

《生活万岁》主演:刘威、王鸥、孙艺洲、代旭

该剧讲述了父亲老曾在昏迷醒来后反思自我,并通过一系列啼笑皆非的事件帮助四个子女找回生活、理解生活、拥抱生活的故事。从剧中看生活本质,从爱中观人间冷暖。而刘威、王鸥、孙艺洲、代旭、陈艳茜等明星,也让这部剧阵容上很有看点。

《温暖的味道》主演:靳东、李乃文

靳东领衔主演,李乃文、吴越、高露、黄曼、赵柯、姜寒主演的当代农村剧,大槐树村任第一书记的故事。

《危机先生》主演:黄晓明、蔡文静、谭卓

该剧讲述了危机公关专家林中硕带领团队,处理了一个又一个棘手的社会公关事件的故事。《延禧攻略》导演惠楷栋拍摄,找到了黄晓明、蔡文静、谭卓等明星,希望能有不一样的惊喜。

《流金岁月》主演:刘诗诗、倪妮

该剧根据亦舒同名小说改编,讲述了蒋南孙和朱锁锁两人一路扶持的友谊并一起成长的故事。刘诗诗、倪妮、陈道明 、董子健、田雨、杨祐宁、杨玏,这个阵容组合还是很不错的。

《王牌部队》主演:黄景瑜、肖战

该剧以党在新形势下的强军目标为引领,聚焦锻造"召之即来、来之能战、战之必胜"精兵劲旅,展现近四十年中国军队的数次变革和军人所经历的非凡岁月,唱响一曲中国人民解放军新时期军魂的赞歌。

《跨过鸭绿江》

英雄集结,奔赴千里,形势之下亮决心,勇锐顽强破悍敌。总台出品,戏骨加持!

主演:丁勇岱、刘之冰、唐国强、姚刚、王志飞、王挺、韩栋、张铎

《大决战》

《大决战》演员阵容强大,老中青演员齐上阵。导演高希希表示:"主要人物均选取与真实历史人物形似神似的实力派演员出演,并尽量选取具有市场号召力和新媒体影响力的青年演员出演,带动更多年轻人了解历史,铭记来之不易的胜利。"

主演:唐国强、刘劲、王伍福、郭连文、王健、刘之冰、卢奇、谷伟、郭广平、于和伟、林永健、邵兵、王亚楠、李健、王挺、王劲松、邢岷山、霍青、赵亮、陈逸恒、何晟铭、李强

《红船》

开天辟地,敢为人先。英雄披荆斩浪,巨轮风起扬帆!这是一段关于诞生和发展的伟大故事,红船精神,时代之光。

《城中之城》

两代金融人的职业抉择和命运起伏,一批坚守职业道德与维护金融秩序的青年群像。奋斗与热血交织。

《热血珠峰》

测的是重责大任,绘的是国泰民安,首度聚焦测绘人,热血巅峰之上,测绘精神闪光。

《天望》

弘扬北斗精神,展现民族自强力量!《天望》作为一部讲述中国成功自主研发"北斗"卫星导航通信系统的重大现实题材作品,让我们见证北斗耀华夏,科技创新生!

据介绍, CSM全国网2019年数据,央视八套全年收视份额达4.62%,连续3年排名全国第一位,并创下自频道开播以来10年的收视新高。今年截至目前,央视八套的收视份额达4.34%,稳居首位。

大家期待央视播出哪些新剧?欢迎留言!返回搜狐,查看更多

责任编辑:

原文转载:http://yl.shaoqun.com/a/208937.html

ad公司:https://www.ikjzd.com/w/1332

智赢:https://www.ikjzd.com/w/1511

国际标准书号:https://www.ikjzd.com/w/174


原标题:央视21年热剧片单!孙俪朱一龙刘诗诗倪妮肖战看好谁11月26日下午,"大剧看总台——中央广播电视总台2021年电视剧片单发布活动"在北京举行。《跨过鸭绿江》《大决战》《红船》《热血珠峰》《城中之城》《天望》《人世间》等多部影视剧主创人员登场,现场还发布了一系列概念海报、定妆照、预告片等物料。而《甜蜜》《生活万岁》《叛逆者》《危机先生》等剧的主创人员,也来到现场宣传新剧。其中,《叛逆者》主演
dojo:dojo
promotion:promotion
清新金龙洞地下河门票多少?:清新金龙洞地下河门票多少?
集装箱船SSL KOLKATA突发大火:近500个集装箱着火,多是中国货物!:集装箱船SSL KOLKATA突发大火:近500个集装箱着火,多是中国货物!
亚马逊印度站上爆款产品及所销国家:亚马逊印度站上爆款产品及所销国家