Java三种方法将List转换为Map的实例【转载】
原文链接:https://www.jb51.net/article/149605.htm
Java三种方法将List转换为Map的实例
1.for循环
1 |
|
2.使用guava
1 |
|
3.使用JDK1.8 lambda表达式
1 |
|
原文链接:https://www.jb51.net/article/149605.htm
1.for循环
1 |
|
2.使用guava
1 |
|
3.使用JDK1.8 lambda表达式
1 |
|
shell中根据指定分隔符将字符串拆分成数组,然后遍历该数组
Shell 脚本中有个变量叫IFS(Internal Field Seprator) ,内部域分隔符。完整定义是The shell uses the value stored in IFS, which is the space, tab, and newline characters by default, to delimit words for the read and set commands, when parsing output from command substitution, and when performing variable substitution.
Shell 的环境变量分为set, env 两种,其中 set 变量可以通过 export 工具导入到 env 变量中。其中,set 是显示设置shell变量,仅在本 shell 中有效;env 是显示设置用户环境变量 ,仅在当前会话中有效。换句话说,set 变量里包含了env 变量,但set变量不一定都是env 变量。这两种变量不同之处在于变量的作用域不同。显然,env 变量的作用域要大些,它可以在 subshell 中使用。
IFS 是一种 set 变量,当 shell 处理”命令替换”和”参数替换”时,shell 根据 IFS 的值,默认是 space, tab, newline 来拆解读入的变量,然后对特殊字符进行处理,最后重新组合赋值给该变量。
echo “$IFS”
不会显示任何内容
echo “$IFS”|od -b
展示内容如下
1 | 0000000 040 011 012 012 |
直接输出IFS是看不到值的,转化为二进制就可以看到了,”040″是空格,”011″是Tab,”012″是换行符”\n” 。最后一个 012 是因为 echo 默认是会换行的。
1 | #!/bin/bash |
1 | #!/bin/bash |
变量
IFS存储着分隔符,这里我们将其设为逗号”,”OLDIFS用于备份默认的分隔符,使用完后将之恢复默认。arr=(IFS存储着分隔符,这里我们将其设为逗号 “,” OLD_IFS用于备份默认的分隔符,使用完后将之恢复默认。
arr=(IFS存储着分隔符,这里我们将其设为逗号“,“OLDIFS用于备份默认的分隔符,使用完后将之恢复默认。arr=(a)用于将字符串
a按IFS分隔符分割到数组a按IFS分隔符分割到数组a按IFS分隔符分割到数组arr
arr[0]{arr[0]}arr[0]{arr[1]} … 分别存储分割后的数组第1 2 … 项
arr[@]存储整个数组。{arr[@]}存储整个数组。arr[@]存储整个数组。{!arr[@]}存储整个索引值:1 2 3 4 …
${#arr[@]} 获取数组的长度。
一台主节点,一台从节点
注意,集群配置完成前建议不要启动单个ES实例。
原因:默认参数启动会以单实例方式启动,创建各种文件夹、文件,可能干扰后续集群配置。
1 | cluster.name: tipdm-es #es集群名称 |
建议新建一个linux用户,用于管理elasticsearch
1 | useradd elasticsearch |
此时即可启动ES
1 | sudo su - elasticsearch |
浏览器中输入服务器:9200 ,显示ES参数,类似
1 | { |
说明配置成功。
将配置好的ES文件夹拷贝到其他节点,修改:
此处给出centos 6上yum安装方式
1 | [root@c6-23 ~]# curl --silent --location https://rpm.nodesource.com/setup_9.x | bash - |
其他可以参考 centos6.6 安装nodejs和npm
分别执行node -v和“npm -v,显示nodejs版本和npm版本,则说明安装成功。
下载head插件
1 | wget https://github.com/mobz/elasticsearch-head/archive/master.zip |
解压
1 | unzip master.zip |
安装grunt
1 | npm install -g grunt-cli |
执行成功后会在当前目录(elasticsearch-head-master)下生成node_modules文件夹。
修改Gruntfile.js文件:增加hostname属性,设置为*。
1 | connect: { |
打开_site/app.js 文件:修改head的连接地址,将this.base_uri = this.config.base_uri || this.prefs.get(“app-base_uri”) || “http://localhost:9200”;这条语句,修改为如下
1 | this.base_uri = this.config.base_uri || this.prefs.get(“app-base_uri”) || “http://ES节点IP:9200”; |
启动head插件,在elasticsearch-head-master下启动服务。在启动前要确认es集群是正常启动了的,然后才能启动head
执行命令grunt server &即可在后台启动head插件。
在浏览器访问“head部署服务器:9100”,即可看到管理界面,类似这样:
配置问题,修改elasticsearch.yml文件,添加
1 | http.cors.enabled: true |
分析原因:
可能是因为elasticsearch-head发送请求的时候,跨域了,所以变成options,让options去发现有什么可以请求的方法,而options请求没有返回结果。
区别一:
1 | # 节点角色 Master |
区别二:
Master 设置了HTTP 相关参数,如果不设置,将无法通过HEAD能插件来访问集群
1 | # |
启动从节点时无法加入到集群,报错信息
1 | Caused by: java.lang.IllegalStateException: failure when sending a validation request to node |
原因:推测是因为该节点之前启动过ES,已经创建了data文件夹,与要加入的集群冲突。
解决:删除data文件夹
参见该文章
ElasticSearch 开发总结—— failed to send join request to master[…] reason RemoteTransportException
ElasticSearch集群节点扩容提示Failed to send join request to master
出现该错误“Truncated incorrect DOUBLE value”时,极有可能是你写的mysql查询语句中所提供的字段,与表中字段类型不匹配。比如字段为字符型的,与数字进行比较,数字两侧没加引号;比如表中字段明明是字符串,但在where语句中偏偏直接写成了a=23而不是a=’23’。
解决:字段改成对应类型即可。
参考:https://zhidao.baidu.com/question/693223458186942564.html
默认情况下,如果在mac终端中执行shell脚本,会弹出窗口展示脚本执行输出。
工作中需求:执行shell脚本,不能展示输出。
解决:
问了下谷歌,搜索出如下答案,亲测可用。
原文:
Open Automator, choose Application, add a Run Shell Script action and put in your Shell command between quotes (if you have a file, you can just drag and drop it).
Other than playing it, now you can save it (as an app anywhere) and even set the icon.
参考资料:
Run a shell script on OS X without having a terminal window appear?
其他参考资料:
不要在Set中使用null,或者把null作为map的键值。使用特殊值代表null会让查找操作的语义更清晰。
如果你想把null作为map中某条目的值,更好的办法是 不把这一条目放到map中,而是单独维护一个”值为null的键集合” (null keys)。Map 中对应某个键的值是null,和map中没有对应某个键的值,是非常容易混淆的两种情况。因此,最好把值为null的键分离开,并且仔细想想,null值的键在你的项目中到底表达了什么语义。
如果你需要在列表中使用null,并且这个列表的数据是稀疏的,使用Map<Integer, E>可能会更高效,并且更准确地符合你的潜在需求。
此外,考虑一下使用自然的null对象——特殊值。举例来说,为某个enum类型增加特殊的枚举值表示null,比如java.math.RoundingMode就定义了一个枚举值UNNECESSARY,它表示一种不做任何舍入操作的模式,用这种模式做舍入操作会直接抛出异常。
如果你真的需要使用null值,但是null值不能和Guava中的集合实现一起工作,你只能选择其他实现。比如,用JDK中的Collections.unmodifiableList替代Guava的ImmutableList
大多数情况下,开发人员使用null表明的是某种缺失情形:可能是已经有一个默认值,或没有值,或找不到值。例如,Map.get返回null就表示找不到给定键对应的值。
Guava用Optional表示可能为null的T类型引用。一个Optional实例可能包含非null的引用(isPresent),也可能什么也不包括(absent)。它从不说包含null值,而是用存在或缺失来表示。
1 | Optional<Integer> possible = Optional.of(5); |
Optional无意直接模拟其他编程环境中的”可选” or “可能”语义,但它们的确有相似之处。
| 方法 | 描述 |
|---|---|
| Optional.of(T) | 创建指定引用的Optional实例,若引用为null则快速失败 |
| Optional.absent() | 创建引用缺失的Optional实例 |
| Optional.fromNullable(T) | 创建指定引用的Optional实例,若引用为null则表示缺失 |
| 方法 | 描述 |
|---|---|
| boolean isPresent() | 如果Optional包含非null的引用(引用存在),返回true |
| T get() | 返回Optional所包含的引用,若引用缺失,则抛出java.lang.IllegalStateException |
| T or(T) | 返回Optional所包含的引用,若引用缺失,返回指定的值 |
| T orNull() | 返回Optional所包含的引用,若引用缺失,返回null |
| Set asSet() | 返回Optional所包含引用的单例不可变集,如果引用存在,返回一个只有单一元素的集合,如果引用缺失,返回一个空集合。 |
使用Optional除了赋予null语义,增加了可读性,最大的优点在于它是一种傻瓜式的防护。Optional迫使你积极思考引用缺失的情况,因为你必须显式地从Optional获取引用。直接使用null很容易让人忘掉某些情形,尽管FindBugs可以帮助查找null相关的问题,但是我们还是认为它并不能准确地定位问题根源。
如同输入参数,方法的返回值也可能是null。和其他人一样,你绝对很可能会忘记别人写的方法method(a,b)会返回一个null,就好像当你实现method(a,b)时,也很可能忘记输入参数a可以为null。将方法的返回类型指定为Optional,也可以迫使调用者思考返回的引用缺失的情形。
当你需要用一个默认值来替换可能的null,请使用Objects.firstNonNull(T, T) 方法。如果两个值都是null,该方法会抛出NullPointerException。Optional也是一个比较好的替代方案,例如:Optional.of(first).or(second).
还有其它一些方法专门处理null或空字符串:emptyToNull(String),nullToEmpty(String),isNullOrEmpty(String)。我们想要强调的是,这些方法主要用来与混淆null/空的API进行交互。当每次你写下混淆null/空的代码时,Guava团队都泪流满面。(好的做法是积极地把null和空区分开,以表示不同的含义,在代码中把null和空同等对待是一种令人不安的坏味道。
注意:本文档基于google guava 28 wiki
连接器
1 | Joiner joiner = Joiner.on("; ").skipNulls(); |
返回Harry; Ron; Hermione
skipNulls()方法是直接忽略null,使用useForNull(String)方法可以给定某个字符串来替换null,即
1 | Joiner joiner = Joiner.on("; ").useForNull("替换字符串"); |
Joiner也可以用来连接对象类型,在这种情况下,它会把对象的toString()值连接起来。
1 | Joiner.on(",").join(Arrays.asList(1, 5, 7)); // returns "1,5,7" |
joiner实例总是不可变的。用来定义joiner目标语义的配置方法总会返回一个新的joiner实例。这使得joiner实例都是线程安全的,你可以将其定义为static final常量。
字符串拆分工具
JDK提供的String.split方法 一些奇怪的地方,例如:会丢弃掉尾部分隔符。
例子:
1 | ",a,,b,".split(",") |
返回结果是:
1 | "", "a", "", "b" |
Splitter则提供了更清晰的接口:
1 | Splitter.on(',') |
返回结果为"foo", "bar", "qux"
| 方法 | 描述 | 示例 |
|---|---|---|
| Splitter.on(char) | 按单个字符拆分 | Splitter.on(‘;’) |
| Splitter.on(CharMatcher) | 按字符匹配器拆分 | Splitter.on(CharMatcher.BREAKING_WHITESPACE) |
| Splitter.on(String) | 按字符串拆分 | Splitter.on(“, “) |
| Splitter.on(Pattern) Splitter.onPattern(String) | 按正则表达式拆分 | Splitter.onPattern(“\r?\n”) |
| Splitter.fixedLength(int) | 按固定长度拆分;最后一段可能比给定长度短,但不会为空 | Splitter.fixedLength(3) |
| 方法 | 描述 |
|---|---|
| omitEmptyStrings() | 从结果中自动忽略空字符串 |
| trimResults() | 移除结果字符串的前导空白和尾部空白 |
| trimResults(CharMatcher) | 给定匹配器,移除结果字符串的前导匹配字符和尾部匹配字符 |
| limit(int) | 限制拆分出的字符串数量 |
注:如果需要返回List而不是数组,则调用splitToList()、而不是split()
splitter实例总是不可变的。用来定义splitter目标语义的配置方法总会返回一个新的splitter实例。这使得splitter实例都是线程安全的,你可以将其定义为static final常量。
可以通过withKeyValueSeparator()指定第二个分隔符,用于从字符串中反序列出一个map,将会返回一个Map<String, String>
例如:对url中的查询字符串"id=123&name=green"进行分割
1 | final Map<String, String> join = Splitter.on("&").withKeyValueSeparator("=").split("id=123&name=green"); |
例如:生产一个查询id: 123,name: green的学生信息的url。
1 | Joiner.on("&").withKeyValueSeparator("=").join(ImmutableMap.of("id", "123", "name", "green")); |
CharMatcher实例首先代表概念1:怎么才算匹配字符?然后它还提供了很多操作概念2:如何处理这些匹配字符?
1 | String noControl = CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); //移除control字符 |
注意:CharMatcher只处理char类型代表的字符;它不能理解0x10000到0x10FFFF的Unicode 增补字符。这些逻辑字符以代理对[surrogate pairs]的形式编码进字符串,而CharMatcher只能将这种逻辑字符看待成两个独立的字符。
1 | any() |
其他:
| 方法 | 描述 |
|---|---|
| anyOf(CharSequence) | 枚举匹配字符。如CharMatcher.anyOf(“aeiou”)匹配小写英语元音 |
| is(char) | 给定单一字符匹配。 |
| inRange(char, char) | 给定字符范围匹配,如CharMatcher.inRange(‘a’, ‘z’) |
此外,CharMatcher还有negate()、and(CharMatcher)和or(CharMatcher)方法。
| 方法 | 描述 |
|---|---|
| collapseFrom(CharSequence, char) | 把每组连续的匹配字符替换为特定字符。如WHITESPACE.collapseFrom(string, ‘ ‘) |
| matchesAllOf(CharSequence) | 测试是否字符序列中的所有字符都匹配。 |
| removeFrom(CharSequence) | 从字符序列中移除所有匹配字符。 |
| retainFrom(CharSequence) | 在字符序列中保留匹配字符,移除其他字符。 |
| trimFrom(CharSequence) | 移除字符序列的前导匹配字符和尾部匹配字符。 |
| replaceFrom(CharSequence, CharSequence) | 用特定字符序列替代匹配字符。 |
所有这些方法返回String,除了matchesAllOf返回的是boolean。
获取字符集时,不要这样:
1 | try { |
而是应该:
1 | bytes = string.getBytes(Charsets.UTF_8); |
Charsets针对所有Java平台都要保证支持的六种字符集提供了常量引用。尝试使用这些常量,而不是通过名称获取字符集实例。
CaseFormat被用来方便地在各种ASCII大小写规范间转换字符串——比如,编程语言的命名规范。CaseFormat支持的格式如下:
| 格式 | 范例 |
|---|---|
| LOWER_CAMEL | lowerCamel |
| LOWER_HYPHEN | lower-hyphen |
| LOWER_UNDERSCORE | lower_underscore |
| UPPER_CAMEL | UpperCamel |
| UPPER_UNDERSCORE | UPPER_UNDERSCORE |
elasticsearch启动时报错:
1 |
|
原因:没有足够的内存供JRE运行
解决:修改es配置参数
1 |
|
修改JVM参数,将其改小即可:
1 |
|