一些常用的集合工具的代码块(缓慢更新XD)
更新记录
虽然经常放鸽子,但是还是要记录一下更新
2017.8.30 更新了listToMap的方法,现在可以指定多个属性进行分组了,例如你要指定一个学生集合,按照名字和年龄相同的放在一组,现在只要调用listToMap(list,"name","age")就好啦 _
鱼的记忆
我发现在项目中常常要用到一些集合的处理,不同的项目我经常会编写自己的集合工具代码块,后来我发现我总是在写一样的代码块(可能是我记性不好吧:),毕竟鱼的记忆只有7秒),所以我意识到了是时候将这些代码块做一些整理,这样以后直接调用就好了。然后我发现markdown很多不错的功能我好像都没用过,以后多试试其他功能。
以后会不断的更新哒,免得总是做重复的无用功。
List to Map
list 转 map 这个还是挺常用的,在java8下可以用收集器很容易就做到,java7的话使用google的guava好像也挺不错,不过我实在不喜欢匿名内部类的写法,所以索性就自己写个啦。so let's start
//小明和小红的一些考试成绩,该类的属性分别是[id,学生姓名,考试科目,考试成绩]
List<StudentScore> studentList = Arrays.asList(
new StudentScore(1,"小明","语文",85),
new StudentScore(2,"小明","数学",90),
new StudentScore(3,"小明","英语",80),
new StudentScore(4,"小红","语文",80),
new StudentScore(5,"小红","数学",80),
new StudentScore(6,"小红","英语",80));
//现在要将集合转换成为 学生姓名 ->[科目] 的map集合
//例如[小明]->[语文,数学,英语] 这样的map集合,该怎么办咧
Java8 Ways
这种情况在做一些集合处理数据的时候有时会出现,那么首先是java8下的写法
//转换(以下代码静态导入了java.util.stream.Collectors下的所有静态方法)
Map<String, List<String>> stuMap = studentScoreList.stream()
.collect(groupingBy(StudentScore::getStudentName
, mapping(StudentScore::getSubjectName, toList())));
//输出
stuMap.forEach((s, strings) -> System.out.println("key: " + s +"\t value: " + strings));
输出结果:
key: 小明 value: [语文, 数学, 英语]
key: 小红 value: [语文, 数学, 英语]
java8在前面的博客已经有介绍了,这里简单说一下,代码第三行将集合按照学生姓名进行了分组,第4行使用了下游收集器,将学生的考试科目名称进行了收集,并且是以list的集合形式收集的,因此就做到了以上的输出效果。
不得不承认,java8的流操作包办了几乎一切集合的操作,确实方便,那么在java7中该怎么做呢,我自己写了工具方法,java7环境要转换的话直接调用就好啦。
Java7 Ways
//转换,三个参数分别是[要转换的集合,作为key值的属性名,作为value值的属性名]
Map<String, List<String>> stuMapJava7 = CollectionUtils.listToMap(studentScoreList, "studentName", "subjectName");
for (Map.Entry<String, List<String>> entry : stuMapJava7.entrySet()) {
System.out.println("key: " + entry.getKey() +"\t value: " + entry.getValue());
}
输出结果:
key: 小明 value: [语文, 数学, 英语]
key: 小红 value: [语文, 数学, 英语]
这里我提供了两个重载方法,一个就是上面演示的三个参数的分别是[要转换的集合,作为key值的属性名,作为value值的属性名],另一个方法提供两个参数分别是[要转的集合,作为key值的属性名],另外一个方法的value值就是对象本身了。下面是代码,方法中我认为比较巧妙的一点是通过对list集合地址内容的修改来完成相关集合的生成。
/**
* 该方法用于list转map的重载方法,可自定义map映射的属性值 by LDF
* @param list 用于转换的初始集合list
* @param key 用于分组的key值,key值可以不唯一,不唯一的话类似于数据库的groupBy操作进行分组
* @param valueProperName value值的属性名
* @param <T> 初始集合list中的对象的泛型
* @param <K> 转换后map集合的value值的泛型
* @return 形如 key -> [valueProperName] 的map集合
*/
public static <T, K> Map<String, List<K>> listToMap(List<T> list, String key, String valueProperName) {
Map<String, List<K>> returnMap = new HashMap<>();
try {
for (T t : list) {
Field name = t.getClass().getDeclaredField(key);//通过反射获得私有属性,这里捕获获取不到属性异常
name.setAccessible(true);//获得访问和修改私有属性的权限
String keyName = name.get(t).toString();//获得key值
List<K> tempList = returnMap.get(keyName);
if (tempList == null) {
tempList = new ArrayList<>();
Field field = t.getClass().getDeclaredField(valueProperName);//同上,通过反射拿到私有属性
field.setAccessible(true);
K k = (K) field.get(t);//强转,这里抛出转换异常
tempList.add(k);//这里的添加已经同步影响到map集合了,因为引用的是地址
returnMap.put(keyName, tempList);
} else {
Field field = t.getClass().getDeclaredField(valueProperName);
field.setAccessible(true);
K k = (K) field.get(t);
tempList.add(k);//这里的添加已经同步影响到map集合了,因为引用的是地址
}
}
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
return returnMap;
}
/**
* <h1 style="color:#007979"> 根据多属性进行list转map分组</h1>
*
* @param list 要转换的集合 by LDF
* @param strings 作为key的属性名,这里可以指定多个属性哦,用逗号分开就可以了,例如要指定名字和年龄都相同的为一组(假设你要转换的集合叫list)参数这里就 填写(list, "name", "age")
* @param <T> 集合里对象的泛型
* @return
*/
public static <T> Map<String, List<T>> listToMap(List<T> list, String... strings) {
Map<String, List<T>> returnMap = new HashMap<>();
try {
for (T t : list) {
StringBuffer stringBuffer = new StringBuffer();
for (String s : strings) {
Field name1 = t.getClass().getDeclaredField(s);//通过反射获得私有属性,这里捕获获取不到属性异常
name1.setAccessible(true);//获得访问和修改私有属性的权限
String key = name1.get(t).toString();//获得key值
stringBuffer.append(key);
}
String KeyName = stringBuffer.toString();
List<T> tempList = returnMap.get(KeyName);
if (tempList == null) {
tempList = new ArrayList<>();
tempList.add(t);
returnMap.put(KeyName, tempList);
} else {
tempList.add(t);
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return returnMap;
}
filter 过滤
- java8Ways
List<StudentScore> filterStuListJava8 = studentScoreList
.stream()
.filter(s -> s.getScore()>=85)
.collect(toList());
System.out.println(filterStuListJava8);
输出结果
[StudentScore{id=1, studentName='小明', subjectName='语文', score=85},
StudentScore{id=2, studentName='小明', subjectName='数学', score=90}]
声明式的链式代码看的确实很爽,那么在java7该如何实现呢
- java7Ways
filter两个参数分别是[需要过滤的集合,过滤条件],返回[过滤后的集合]
List<StudentScore> filterStuListMy = filter(studentScoreList, new IPredicate<StudentScore>() {
@Override
public boolean apply(StudentScore studentScore) {
return studentScore.getScore() >= 85;
}
});
System.out.println(filterStuListMy);
输出结果
[StudentScore{id=1, studentName='小明', subjectName='语文', score=85},
StudentScore{id=2, studentName='小明', subjectName='数学', score=90}]
那么是如何实现这样的效果的咧
依旧是写了辅助类来实现声明式的效果
首先是一个函数接口
//@FunctionalInterface(java7 中没有该注释)
public interface IPredicate<T> {
boolean apply(T t);
}
然后是一个实现方法
/**
* 该方法接受一个需要过滤的集合和一个过滤条件(通过重写接口的apply方法来定义条件) by LDF
* @param t 需要过滤的集合
* @param iPredicate 过滤的条件
* @param <T> 集合的泛型类
* @return 过滤后的集合
*/
public static <T> List<T> filter(List<T> t, IPredicate<? super T> iPredicate){
List<T> returnList = new ArrayList<>();
for (T t1 : t) {
if (iPredicate.apply(t1)) {
returnList.add(t1);
}
}
return returnList;
}
ps:你还可以使用google的guava集合类库完成过滤操作,操作方法十分相似,区别是guava的返回值为Collection,而自定义的方法就比较灵活了
带条件的distinc
java8流操作的已经包含了distinc了,但是该distinc是不带条件的,如果想要根据集合的某一个属性来去重,该怎么办咧?代码如下
例如要根据学生姓名来去重
//去重
studentScoreList.stream()
.filter(distinctByKey(StudentScore::getStudentName))
.forEach(System.out::println);
去重方法如下,利用一个map集合将第一次看见的值放入,并标记为true,然后用该map里的值与Null作对比(因为如果是null的话就证明这条数据没出现过,因此是非重复的数据,可以通过过滤)
备注:该方法来自于Oracle的Stuart Marks(java8的开发者)与 Tagir Valeev(IntelliJ IDEA的开发者)的修正
/**
* 该方法根据集合中对象的某一个属性进行去重
* @param keyExtractor 去重的条件属性
* @param <T>
* @return
*/
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object,Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;}
tip:写例子的时候有时候发现function或者Predicate的接口参数编译器总是不通过,找了半天发现原来是guava包里的两个弄混了(因为是同名),这点大家还是要注意一哈:)
一些常用的集合工具的代码块(缓慢更新XD)的更多相关文章
- 一些常用的集合工具的代码块(缓慢更新XD,更新了多属性过滤:) )
更新记录 虽然经常放鸽子,但是还是要记录一下更新 2017.8.30 更新了listToMap的方法,现在可以指定多个属性进行分组了,例如你要指定一个学生集合,按照名字和年龄相同的放在一组,现在只要调 ...
- java提高篇(十二)-----代码块
在编程过程中我们可能会遇到如下这种形式的程序: public class Test { { //// } } 这种形式的程序段我们将其称之为代码块,所谓代码块就是用大括号({})将多行代码封装在一起, ...
- java提高篇(十一)-----代码块
在编程过程中我们可能会遇到如下这种形式的程序: public class Test { { //// } } 这种形式的程序段我们将其称之为代码块,所谓代码块就是用大括号({})将多行代码封装在一起, ...
- HBuilder js 自定义代码块
=begin 本文档是HBuilder预置的js代码块的文件.注意不要把其他语言的设置放到js里来. 如果用户修改此文档,HBuilder升级后会覆盖用户的修改,建议进入菜单 工具→扩展代码块 扩展相 ...
- 牛客网Java刷题知识点之什么是代码块、普通代码块、静态代码块、同步代码块、构造代码块以及执行顺序
不多说,直接上干货! 这种形式的程序段我们将其称之为代码块,所谓代码块就是用大括号({})将多行代码封装在一起,形成一个独立的数据体,用于实现特定的算法.一般来说代码块是不能单独运行的,它必须要有运行 ...
- 一些日常工具集合(C++代码片段)
一些日常工具集合(C++代码片段) ——工欲善其事,必先利其器 尽管不会松松松,但是至少维持一个比较小的常数还是比较好的 在此之前依然要保证算法的正确性以及代码的可写性 本文依然会持久更新,因为一次写 ...
- 站长常用的200个js代码 站长常用js代码大全 站长常用js代码集合
站长常用的200个js代码 1.文本框焦点问题 onBlur:当失去输入焦点后产生该事件 onFocus:当输入获得焦点后,产生该文件 Onchange:当文字值改变时,产生该事件 Onselect: ...
- 控件包含代码块(即 <% ... %>),因此无法修改控件集合
错误: “/”应用程序中的服务器错误. 控件包含代码块(即 <% ... %>),因此无法修改控件集合. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解 ...
- asp.net 中的那些编译错误(1):控件包含代码块(即<% ... %>),因此无法修改控件集合
在编译页面的时候出现:控件包含代码块(即 <% ... %>),因此无法修改控件集合错误 一般原因是: 在<head runat="server">< ...
随机推荐
- Vijos 1002 过河 状态压缩DP
描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上 ...
- voa 2015 / 4 / 15
illustrated - v. to explain or decorate a story, book, etc., with pictures pediatrician – n. a docto ...
- vue的增删改查
我们把这些用户信息保存到list的数组中,然后增删改查就在这个数组上进行: list: [ { username: 'aaaaa', email: '123@qq.com', sex: '男', pr ...
- webgl自学笔记——几何图形
3D应用的基础元素: 1.canvas,它是渲染场景的占位符.标准html的canvas元素 2.Objects,这里指的是组成一个场景的所有3d实体.这些实体都由三角形组成.webgl中使用Buff ...
- java Semaphore的介绍和使用
一个计数信号量.从概念上讲,信号量维护了一个许可集.如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可.每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者. ...
- java多线程系列(二)
对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...
- Java版 QQ空间自动登录无需拷贝cookie一天抓取30WQQ说说数据&流程分析
QQ空间说说抓取难度比较大,花了一个星期才研究清楚! 代码请移步到GitHub GitHub地址:https://github.com/20100507/Qzone [没有加入多线程,希望你可以参与进 ...
- OI内的排列与组合(简单版)
§1基本原理 △让我们来看下面问题: 从甲地到乙地,可以乘火车,也可以乘汽车,还可以乘轮船.一天中,火车有4班,汽车有2班,轮船有3班.那么,一天中乘坐这些交通工具从甲地到乙地共有多少种不同走法?△分 ...
- 学习笔记TF032:实现Google Inception Net
Google Inception Net,ILSVRC 2014比赛第一名.控制计算量.参数量,分类性能非常好.V1,top-5错误率6.67%,22层,15亿次浮点运算,500万参数(AlexNet ...
- Hbase单机安装部署
Hbase单机安装部署 http://blogxinxiucan.sh1.newtouch.com/2017/07/27/Hbase单机安装部署/ 下载Hbase Hbase官网下载地址 http:/ ...