使用toMap()函数之后,返回的就是一个Map了,自然会需要key和value。
toMap()的第一个参数就是用来生成key值的,第二个参数就是用来生成value值的,第三个参数用在key值冲突的情况下,如果新元素产生的key在Map中已经出现过了,第三个参数就会定义解决的办法。
List indices = getIndices(brokerId, null);
Map testMap = indices.stream().collect(Collectors.toMap(Student::getName, Function.identity(), (k1, k2) -> k1));
在这个例子中 Student::getName, Function.identity(), (k1, k2) -> k1)
第一个参数Student::getName 表示选择Student的getName作为map的key值;
第二个参数 Function.identity() 表示选择将原来的对象Student作为map的value值;
第三个参数(v1, v2) -> v1中,如果v1与v2的key值相同,选择v1作为那个key所对应的value值
Function.identity()返回一个输出跟输入一样的Lambda表达式对象,等价于形如t -> t形式的Lambda表达式。上面的例子就是说indices的对象Student作为value值。
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
https://blog.csdn.net/qq_30546099/article/details/113933979
1.map:映射每个元素所对应的结果;
2.collect:Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串
将流转换为集合赋值给balanceCoinVOS
lambda表达式,意思就是 -> 左侧的作为参数,计算出 -> 右侧的数据,然后存到集合中。
eg:
public static void main(String[] args) {
List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List squaresList = numbers
.stream()
.map( i -> i*i)
.distinct()
.collect(Collectors.toList());
for (Integer i:squaresList) {
System.out.println(i);
}
}
结果
9
4
49
25
生成流
在 Java 8 中, 集合接口有两个方法来生成流:
forEach
Stream 提供了新的方法 'forEach' 来迭代流中的每个数据。以下代码片段使用 forEach 输出了10个随机数:
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
map
map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:
List
numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); // 获取对应的平方数 List squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList()); filter
filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:
List
strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 获取空字符串的数量 long count = strings.stream().filter(string -> string.isEmpty()).count(); limit
limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据:
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
sorted
sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);
并行(parallel)程序
parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量:
List
strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 获取空字符串的数量 long count = strings.parallelStream().filter(string -> string.isEmpty()).count(); 我们可以很容易的在顺序运行和并行直接切换。
Collectors
Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
List
strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("筛选列表: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("合并字符串: " + mergedString); findFirst() 方法
返回流中第一个元素,如下所示
Optional first = Stream.of(2, 4, 6, 8, 9, 1, 3).findFirst(); System.out.println(first.get()); 如上代码,始终返回2
讲的CollectionUtils工具类是在apache下的, 而不是springframework下的CollectionUtils。
个人觉得CollectionUtils在真实项目中,可以使你的代码更加简洁和安全。
所以需要倒入相关jar包,目前从maven找到最新jar包如下:
org.apache.commons
commons-collections4
4.3
API常用方法
/**
* 1、除非元素为null,否则向集合添加元素
*/
CollectionUtils.addIgnoreNull(personList,null);
/**
* 2、将两个已排序的集合a和b合并为一个已排序的列表,以便保留元素的自然顺序
*/
CollectionUtils.collate(Iterable extends O> a, Iterable extends O> b)
/**
* 3、将两个已排序的集合a和b合并到一个已排序的列表中,以便保留根据Comparator c的元素顺序。
*/
CollectionUtils.collate(Iterable extends O> a, Iterable extends O> b, Comparator super O> c)
/**
* 4、返回该个集合中是否含有至少有一个元素
*/
CollectionUtils.containsAny(Collection> coll1, T... coll2)
/**
* 5、如果参数是null,则返回不可变的空集合,否则返回参数本身。(很实用 ,最终返回List EMPTY_LIST = new EmptyList<>())
*/
CollectionUtils.emptyIfNull(Collection collection)
/**
* 6、空安全检查指定的集合是否为空
*/
CollectionUtils.isEmpty(Collection> coll)
/**
* 7、 空安全检查指定的集合是否为空。
*/
CollectionUtils.isNotEmpty(Collection> coll)
/**
* 8、反转给定数组的顺序。
*/
CollectionUtils.reverseArray(Object[] array);
/**
* 9、差集
*/
CollectionUtils.subtract(Iterable extends O> a, Iterable extends O> b)
/**
* 10、并集
*/
CollectionUtils.union(Iterable extends O> a, Iterable extends O> b)
/**
* 11、交集
*/
CollectionUtils.intersection(Collection a, Collection b)
/**
*12、 交集的补集(析取)
*/
CollectionUtils.disjunction(Collection a, Collection b)
一、emptyList()
1. new ArrayList()创建时有初始大小,占用内存,emptyList()不用创建一个新的对象,可以减少内存开销;
2. 方法返回一个emptyList()时,不会报空指针异常,如果直接返回Null,没有进行非空判断就会报空指针异常;
@Test
public void test1() {
String str = "";
List list = getList(str);
System.out.println(list.size());
}
private static List getList(String str) {
if (StringUtils.isBlank(str)) {
// 使用时不会报空指针
return Collections.emptyList();
// 使用null报空指针异常
// return null;
}
List list = new ArrayList();
list.add(str);
return list;
}
@Test
public void test2() {
String str = "abc";
List list = Collections.emptyList();
list.add(str);
System.out.println(list.size());
}
Arrays.asList
1.Arrays.asList() 将数组转化为list集合的方法
注意:
(1)该方法适用于对象型数据的数组(String、Integer...)
(2)该方法不建议使用于基本数据类型的数组(byte,short,int,long,float,double,boolean)
(3)该方法将数组与List列表链接起来:当更新其一个时,另一个自动更新
(4)不支持add()、remove()、clear()等方法
【2.Arrays.asList()是个坑】
用此方法得到的List的长度是不可改变的,
当你向这个List添加或删除一个元素时(例如 list.add("d");)程序就会抛出异常(java.lang.UnsupportedOperationException)。 怎么会这样?只需要看看asList()方法是怎么实现的就行了:
public static
当你看到这段代码时可能觉得没啥问题啊,不就是返回了一个ArrayList对象吗?问题就出在这里。
这个ArrayList不是java.util包下的,而是java.util.Arrays.ArrayList
它是Arrays类自己定义的一个静态内部类,这个内部类没有实现add()、remove()方法,而是直接使用它的父类AbstractList的相应方法。
而AbstractList中的add()和remove()是直接抛出java.lang.UnsupportedOperationException异常的!
public void add(int index, E element) { throw new UnsupportedOperationException();}
public E remove(int index) {throw new UnsupportedOperationException();}
总结:如果你的List只是用来遍历,就用Arrays.asList()。
如果你的List还要添加或删除元素,还是乖乖地new一个java.util.ArrayList,然后一个一个的添加元素。
JDK内建的字符串拆分工具有一些古怪的特性。比如,String.split悄悄丢弃了尾部的分隔符。 问题:”,a,,b,”.split(“,”)返回?
正确答案是5:””, “a”, “”, “b”。只有尾部的空字符串被忽略了。 Splitter使用令人放心的、直白的流畅API模式对这些混乱的特性作了完全的掌控。
Splitter.on(',')
.trimResults()
.omitEmptyStrings()
.split("foo,bar,, qux");
上述代码返回Iterable
拆分器工厂
方法 |
描述 |
范例 |
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,只要使用Lists.newArrayList(splitter.split(string))或类似方法。 警告:splitter实例总是不可变的。用来定义splitter目标语义的配置方法总会返回一个新的splitter实例。这使得splitter实例都是线程安全的,你可以将其定义为static final常量。
eg:
String s1 = "hello|hihi";
String s2 = "hello|haha|||";
List list = Splitter.on("|").splitToList(s1);
List list2 = Splitter.on("|").splitToList(s2);
System.out.println(list);
System.out.println(list2);
结果
[hello, hihi]
[hello, haha, , , ]
使用后创建一个无参构建函数
使用后添加一个构建函数。该构造函数含有所有已声明字段属性参数
使用这个注解,就不用再去手写Getter,Setter,equals,canEqual,hasCode,toString等方法了,注解后在编译时会自动加进去。
eg:@ApiModelProperty(value = "是否过滤交易账户持仓(1:过滤 2:不过滤)", name = "filterTradeAccount", dataType = "String", required = false, example = "1")
value:属性的中文描述
name:重写属性名
dataType:重写属性类型
required:是否必须
example:举例说明
hidden:隐藏
1.就是用于swagger提供开发者文档,文档中生成的注释内容。
@ApiOperation( value = "编辑公告", notes = "编辑公告", httpMethod = "POST" )
@RequestMapping( value = "/edit", method = RequestMethod.POST )
public RequestResult edit(
@ApiParam(name = "title", value = "公告标题", required = true) @RequestParam("title") String title,
@ApiParam(name = "content", value = "公告内容", required = true) @RequestParam("content") String content){
是获取前端传递给后端的参数,可以是get方式,也可以是post方式。
其中如果前端传递的参数和后端你接受的参数起的名字字段是一致的可以省略不写,所以@RequestParam("title") String title 也可以直接写@RequestParam String title。
如果不一致一定要完整写,不然获取不到,如下面的bis_key就必须写。
@ApiOperation( value = "编辑公告", notes = "编辑公告", httpMethod = "POST" )
@RequestMapping( value = "/edit", method = RequestMethod.POST )
public RequestResult edit(
@ApiParam(name = "bis_key", value = "bis_key", required = true)@RequestParam("bis_key") String bisKey,
@ApiParam(name = "title", value = "公告标题", required = true) @RequestParam String title,
@ApiParam(name = "content", value = "公告内容", required = true) String content,
是获取get方式,url后面参数,进行参数绑定
@ApiOperation(value = "删除公告", notes = "删除公告", httpMethod = "POST")
@RequestMapping(value = "/delete/{bisKey}", method = RequestMethod.POST)
public RequestResult remove(@ApiParam(name = "bisKey", value = "需要删除的公告ids", required = true) @PathVariable String bisKey) {
@Builder
public class Card {
private int id;
private String name;
private boolean sex;
}
使用:
Card card = Card.builder().id(10).name("dasd").sex(true).build();
优点:
@Builder对类做了什么
我们可以反编译生成的Card.class
public class Card {
private int id;
private String name;
private boolean sex;
Card(int id, String name, boolean sex) {
this.id = id;
this.name = name;
this.sex = sex;
}
public static Card.CardBuilder builder() {
return new Card.CardBuilder();
}
public static class CardBuilder {
private int id;
private String name;
private boolean sex;
CardBuilder() {
}
public Card.CardBuilder id(int id) {
this.id = id;
return this;
}
public Card.CardBuilder name(String name) {
this.name = name;
return this;
}
public Card.CardBuilder sex(boolean sex) {
this.sex = sex;
return this;
}
public Card build() {
return new Card(this.id, this.name, this.sex);
}
public String toString() {
return "Card.CardBuilder(id=" + this.id + ", name=" + this.name + ", sex=" + this.sex + ")";
}
}
}
看上面编译后的class类就很明显,注解在编译后使得Card类中多了一个名为Card.CardBuilder的静态内部类。这个静态内部类拥有和Card类相同的属性,并且额外实现了一些方法:
1.name、sex、id等的属性方法
其实这些方法和setAttribute十分类似,只是额外返回了实例本身,这使得它可以使用类似于链式调用的写法。
2.build方法
该方法调用Card类的全参构造方法来生成Card实例。
Card类还是实现了builder方法,这个方法生成一个空的Card.CardBuilder实例。
缺点
最明显的一点,在生成Card实例之前,实际上是先创建了一个Card.CardBuilder实例,这样很明显额外占用了内存。
额外
@Builder(toBuilder = true)
这个选项允许你将一个实例化好的Card更新字段生成新的Card实例。
public Card.CardBuilder toBuilder() {
return (new Card.CardBuilder()).id(this.id).name(this.name).sex(this.sex);
}
可以清楚的看出来,toBuilder方法是用当前实例的属性构造了一个新的Builder实例。
eg:
BalanceDollarInnerVO.BalanceDollarInnerVOBuilder balanceDollarVoBuilder = BalanceDollarInnerVO.builder()
.details(balanceCoinVOS)
.uTime(accountBalanceBO.getUTime() + "")
.totalEq(accountBalanceBO.getTotalEq());
...... 中间对balanceDollarVoBuilder进行一些赋值
return balanceDollarVoBuilder.build();
builder()方法
BalanceDollarInnerVO通过@Builder生成一个静态内部类BalanceDollarInnerVOBuilder,然后调用.builder()方法返回该BalanceDollarInnerVO对象
不用再去声明set方法
作用之一为了解决在某个类有很多构造函数的情况,也省去写很多构造函数的麻烦,在设计模式中的思想是:用一个内部类去实例化一个对象,避免一个类出现过多构建函数。
Builder使用创建者模式又叫建造者模式。简单来说,就是一步步创建一个对象,他对用户屏蔽了里面构建的细节,但却可以精细的控制对象的构造过程。
@Builder的作用:
生成一个全属性的构造器
生成了一个返回静态内部类PersonBuilder对象的方法
生成了一个静态内部类PersonBuilder,这个静态内部类包含Person类的三个属性,无参构造器,三个方法名为属性名的方法,返回Person对象的build方法,输出静态内部类三个属性的toString()方法。
⑤ 建造者使用过程:
1 2 3 4 5 |
Person.PersonBuilder builder = Person.builder(); builder.phoneNumeber("11111") .id("1123") .name("asdd").build(); System.out.println(builder); |
先实例化内部类对象并返回,然后为调用内部类的方法为内部类的属性赋值,build()方法就是将内部类PersonBuilder的属性值传入Person构造器中,实例化Person对象。
以上即为对于@Builder的简单使用。
@ApiIgnore 注解
@ApiIgnore 注解主要作用在方法上,类上,参数上。
当作用在方法上时,方法将被忽略;作用在类上时,整个类都会被忽略;作用在参数上时,单个具体的参数会被忽略。
@ApiIgnore 可以用在类、方法上,方法参数中,用来屏蔽某些接口或参数,使其不在页面上显示。
// 真个类被 Swagger 忽略
@ApiIgnore
@RestController
@RequestMapping(value = "/xttblog")
public class XttblogController {}
@RestController
@RequestMapping(value = "/xttblog")
public class XttblogController {
// 整个方法被忽略
@ApiIgnore
public String hello(){
return "hello";
}
// Swagger 上 忽略 User 参数
public String sayHello(@ApiIgnore User user){
return "hello " + user.getName();
}
}