工作中常用到一些集合的操作,Java8的新特性提供了stream的流操作,大大方便了集合的使用,这里详细总结下日常用的一些操作,下次用到的时候拿来即用,以备遗忘,同时自己也实现一遍,这样印象更深刻些
要操作的对象
首先定义要操作的对象代码清单,包括人员信息
package com.example.springboot.jackson; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.time.LocalDate; import java.util.List; import java.util.Map; import java.util.Set; /** * The type Person. * * @author tianmaolin004 * @date 2023 /3/18 */ @Data @Builder @AllArgsConstructor @NoArgsConstructor public class Person { private String name; private Integer age; private List<String> interests; private Map<String,Integer> scores; private Set<String> loveMovies; private LocalDate birthday; private String school; }
和学校信息:
package com.example.springboot.jackson; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; /** * @author tianmaolin004 * @date 2023/3/19 */ @Data @Builder @AllArgsConstructor @NoArgsConstructor public class School { private String school; }
原始数据准备
要操作的集合原始数据准备:
Person person1 = Person.builder() .name("tml") .age(24) .school("CUB") .build(); Person person2 = Person.builder() .name("gcy") .age(23) .school("ZENDX") .build(); Person person3 = Person.builder() .name("wc") .age(28) .school("CUB") .build(); List<Person> personList = new ArrayList<>(); personList.add(person1); personList.add(person2); personList.add(person3); System.out.println("原始集合====================================="); System.out.println(personList);
集合常用操作
集合的常用操作分为5部分
1 LIST集合相关用法
操作代码如下
// 1 LIST集合相关用法 System.out.println(""); System.out.println("LIST集合相关用法====================================="); System.out.println("filter用法"); List<Person> filter = personList.stream().filter(x -> x.getSchool().equals("CUB")).collect(Collectors.toList()); System.out.println(filter); System.out.println("map用法"); List<Integer> map = personList.stream().map(Person::getAge).collect(Collectors.toList()); System.out.println(map); System.out.println("sort用法"); List<Person> sort = personList.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList()); System.out.println(sort); System.out.println("limit用法"); List<Person> limit = personList.stream().limit(1).collect(Collectors.toList()); System.out.println(limit); System.out.println("limit深拷贝用法"); List<Person> deepCopy = JsonUtils.deepCopy(personList, new TypeReference<List<Person>>() { }); System.out.println(deepCopy); System.out.println("remove用法"); deepCopy.removeIf(x -> x.getAge().equals(28)); System.out.println(deepCopy);
运行结果如下
2 LIST转LIST相关用法
操作代码如下
System.out.println(""); System.out.println("LIST转LIST====================================="); List<School> schools = personList.stream().map(x -> { School school = new School(); school.setSchool(x.getSchool()); return school; }).collect(Collectors.toList()); System.out.println(schools);
运行结果如下
3 LIST转MAP相关用法
操作代码如下
//3 LIST转Map System.out.println(""); System.out.println("LIST转Map====================================="); System.out.println("list按照分组转Map用法"); Map<String, List<Person>> listConvertMap = personList.stream().collect(Collectors.groupingBy(Person::getSchool)); System.out.println(listConvertMap); System.out.println("list按照对象字段转Map用法"); Map<String, Person> listFieldMap = personList.stream().collect(Collectors.toMap(Person::getName, x -> x)); System.out.println(listFieldMap); System.out.println("list按照对象抽离字段字段转Map用法"); Map<String, String> listGetFieldMap = personList.stream().collect(Collectors.toMap(Person::getName, Person::getSchool)); System.out.println(listGetFieldMap);
运行结果如下
4 MAP集合相关用法相关用法
操作代码如下
// 4 Map集合相关用法 System.out.println(""); System.out.println("Map集合相关用法====================================="); System.out.println(personList); System.out.println("遍历Map用法"); listConvertMap.forEach((x, y) -> { if (x.equals("CUB")) { Set<String> loveMovies = new HashSet<>(); loveMovies.add("士兵突击"); loveMovies.add("士兵突击"); loveMovies.add("爱乐之城"); y.stream().forEach(t -> t.setLoveMovies(loveMovies)); } }); System.out.println(listConvertMap);
运行结果如下
5 字符串集合相关操作
操作代码如下
// 5 字符串集合相关操作 System.out.println(""); System.out.println("字符串集合相关操作====================================="); List<String> strings = Arrays.asList("abc", "", "abc", "efg", "add", "", "jkl"); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("合并字符串: " + mergedString); String mergedDistinctString = strings.stream().filter(string -> !string.isEmpty()).distinct().collect(Collectors.joining(", ")); System.out.println("合并去重字符串: " + mergedDistinctString); String[] strConvertList = StringUtils.split(mergedDistinctString, ","); System.out.println("字符串转集合:" + Arrays.asList(strConvertList)); List<List<String>> parts = Lists.partition(strings, 2); System.out.println("字符串分组: " + parts); parts.forEach(System.out::println);
运行结果如下
全部操作代码清单
集合常用操作测试代码如下:
package com.example.springboot.jackson; import com.fasterxml.jackson.core.type.TypeReference; import com.google.common.collect.Lists; import org.apache.commons.lang3.StringUtils; import java.util.*; import java.util.stream.Collectors; /** * @author tianmaolin004 * @date 2023/3/18 */ public class ListTest { public static void main(String[] args) { Person person1 = Person.builder() .name("tml") .age(24) .school("CUB") .build(); Person person2 = Person.builder() .name("gcy") .age(23) .school("ZENDX") .build(); Person person3 = Person.builder() .name("wc") .age(28) .school("CUB") .build(); List<Person> personList = new ArrayList<>(); personList.add(person1); personList.add(person2); personList.add(person3); System.out.println("原始集合====================================="); System.out.println(personList); // 1 LIST集合相关用法 System.out.println(""); System.out.println("LIST集合相关用法====================================="); System.out.println("filter用法"); List<Person> filter = personList.stream().filter(x -> x.getSchool().equals("CUB")).collect(Collectors.toList()); System.out.println(filter); System.out.println("map用法"); List<Integer> map = personList.stream().map(Person::getAge).collect(Collectors.toList()); System.out.println(map); System.out.println("sort用法"); List<Person> sort = personList.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList()); System.out.println(sort); System.out.println("limit用法"); List<Person> limit = personList.stream().limit(1).collect(Collectors.toList()); System.out.println(limit); System.out.println("limit深拷贝用法"); List<Person> deepCopy = JsonUtils.deepCopy(personList, new TypeReference<List<Person>>() { }); System.out.println(deepCopy); System.out.println("remove用法"); deepCopy.removeIf(x -> x.getAge().equals(28)); System.out.println(deepCopy); //2 LIST转LIST System.out.println(""); System.out.println("LIST转LIST====================================="); List<School> schools = personList.stream().map(x -> { School school = new School(); school.setSchool(x.getSchool()); return school; }).collect(Collectors.toList()); System.out.println(schools); //3 LIST转Map System.out.println(""); System.out.println("LIST转Map====================================="); System.out.println("list按照分组转Map用法"); Map<String, List<Person>> listConvertMap = personList.stream().collect(Collectors.groupingBy(Person::getSchool)); System.out.println(listConvertMap); System.out.println("list按照对象字段转Map用法"); Map<String, Person> listFieldMap = personList.stream().collect(Collectors.toMap(Person::getName, x -> x)); System.out.println(listFieldMap); System.out.println("list按照对象抽离字段字段转Map用法"); Map<String, String> listGetFieldMap = personList.stream().collect(Collectors.toMap(Person::getName, Person::getSchool)); System.out.println(listGetFieldMap); // 4 Map集合相关用法 System.out.println(""); System.out.println("Map集合相关用法====================================="); System.out.println(personList); System.out.println("遍历Map用法"); listConvertMap.forEach((x, y) -> { if (x.equals("CUB")) { Set<String> loveMovies = new HashSet<>(); loveMovies.add("士兵突击"); loveMovies.add("士兵突击"); loveMovies.add("爱乐之城"); y.stream().forEach(t -> t.setLoveMovies(loveMovies)); } }); System.out.println(listConvertMap); // 5 字符串集合相关操作 System.out.println(""); System.out.println("字符串集合相关操作====================================="); List<String> strings = Arrays.asList("abc", "", "abc", "efg", "add", "", "jkl"); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("合并字符串: " + mergedString); String mergedDistinctString = strings.stream().filter(string -> !string.isEmpty()).distinct().collect(Collectors.joining(", ")); System.out.println("合并去重字符串: " + mergedDistinctString); String[] strConvertList = StringUtils.split(mergedDistinctString, ","); System.out.println("字符串转集合:" + Arrays.asList(strConvertList)); List<List<String>> parts = Lists.partition(strings, 2); System.out.println("字符串分组: " + parts); parts.forEach(System.out::println); } }
运行结果如下:
原始集合===================================== [Person(name=tml, age=24, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB), Person(name=gcy, age=23, interests=null, scores=null, loveMovies=null, birthday=null, school=ZENDX), Person(name=wc, age=28, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB)] LIST集合相关用法===================================== filter用法 [Person(name=tml, age=24, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB), Person(name=wc, age=28, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB)] map用法 [24, 23, 28] sort用法 [Person(name=gcy, age=23, interests=null, scores=null, loveMovies=null, birthday=null, school=ZENDX), Person(name=tml, age=24, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB), Person(name=wc, age=28, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB)] limit用法 [Person(name=tml, age=24, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB)] limit深拷贝用法 [Person(name=tml, age=24, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB), Person(name=gcy, age=23, interests=null, scores=null, loveMovies=null, birthday=null, school=ZENDX), Person(name=wc, age=28, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB)] remove用法 [Person(name=tml, age=24, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB), Person(name=gcy, age=23, interests=null, scores=null, loveMovies=null, birthday=null, school=ZENDX)] LIST转LIST===================================== [School(school=CUB), School(school=ZENDX), School(school=CUB)] LIST转Map===================================== list按照分组转Map用法 {CUB=[Person(name=tml, age=24, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB), Person(name=wc, age=28, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB)], ZENDX=[Person(name=gcy, age=23, interests=null, scores=null, loveMovies=null, birthday=null, school=ZENDX)]} list按照对象字段转Map用法 {tml=Person(name=tml, age=24, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB), wc=Person(name=wc, age=28, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB), gcy=Person(name=gcy, age=23, interests=null, scores=null, loveMovies=null, birthday=null, school=ZENDX)} list按照对象抽离字段字段转Map用法 {tml=CUB, wc=CUB, gcy=ZENDX} Map集合相关用法===================================== [Person(name=tml, age=24, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB), Person(name=gcy, age=23, interests=null, scores=null, loveMovies=null, birthday=null, school=ZENDX), Person(name=wc, age=28, interests=null, scores=null, loveMovies=null, birthday=null, school=CUB)] 遍历Map用法 {CUB=[Person(name=tml, age=24, interests=null, scores=null, loveMovies=[士兵突击, 爱乐之城], birthday=null, school=CUB), Person(name=wc, age=28, interests=null, scores=null, loveMovies=[士兵突击, 爱乐之城], birthday=null, school=CUB)], ZENDX=[Person(name=gcy, age=23, interests=null, scores=null, loveMovies=null, birthday=null, school=ZENDX)]} Map转List用法 字符串集合相关操作===================================== 合并字符串: abc, abc, efg, add, jkl 合并去重字符串: abc, efg, add, jkl 字符串转集合:[abc, efg, add, jkl] 字符串分组: [[abc, ], [abc, efg], [add, ], [jkl]] [abc, ] [abc, efg] [add, ] [jkl] Process finished with exit code 0
深拷贝相关代码如下:
package com.example.springboot.jackson; import com.alibaba.druid.util.StringUtils; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; /** * The type Json operator. * * @author tianmaolin004 * @date 2023 /3/18 */ @Slf4j public class JsonUtils { private static final ObjectMapper objectMapper = new ObjectMapper(); private static final String LOCAL_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; static { // 1 序列化及反序列化的时间配置 JavaTimeModule timeModule = new JavaTimeModule(); timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE)); timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE)); timeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME)); timeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ISO_LOCAL_TIME)); timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(LOCAL_DATE_TIME_PATTERN))); timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(LOCAL_DATE_TIME_PATTERN))); objectMapper.registerModule(timeModule); objectMapper.setDateFormat(new SimpleDateFormat(LOCAL_DATE_TIME_PATTERN)); //2 忽略反序列化时,对象不存在对应属性的错误,如果不存在该属性,则设置值为null objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); //3 忽略序列化时值为Null元素,不存在该元素,则字符串中无该元素,而不是展示为null objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); } /** * 对象转字符串 * * @param <T> the type parameter * @param obj the obj * @return the string */ public static <T> String obj2Str(T obj) { if (obj == null) { return null; } try { return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj); } catch (Exception e) { log.error("obj2Str fail"); return null; } } /** * 字符串转对象 * * @param <T> the type parameter * @param str the str * @param clazz the clazz * @return the t */ public static <T> T str2Obj(String str, Class<T> clazz) { if (StringUtils.isEmpty(str) || clazz == null) { return null; } try { return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz); } catch (Exception e) { log.error("str2Obj fail"); return null; } } /** * 字符串转对象:泛型模式,一般用于集合 * * @param <T> the type parameter * @param str the str * @param typeReference the type reference * @return the t */ public static <T> T str2Obj(String str, TypeReference<T> typeReference) { if (StringUtils.isEmpty(str) || typeReference == null) { return null; } try { return (T) (typeReference.getType().equals(String.class) ? str : objectMapper.readValue(str, typeReference)); } catch (Exception e) { log.error("str2Obj fail"); return null; } } /** * 字符串转JsonNode * * @param str the str * @return the json node */ public static JsonNode str2JsonNode(String str) { if (StringUtils.isEmpty(str)) { return null; } try { return objectMapper.readTree(str); } catch (Exception e) { log.error("str2Obj fail"); return null; } } /** * 对象互转 * * @param <T> the type parameter * @param fromValue the from value * @param toValueType the to value type * @return the t */ public static <T> T convertValue(@NonNull Object fromValue, @NonNull Class<T> toValueType) { try { return objectMapper.convertValue(fromValue, toValueType); } catch (Exception e) { log.error("str2Obj fail"); return null; } } /** * 对象互转泛型模式 * * @param <T> the type parameter * @param fromValue the from value * @param toValueTypeRef the to value type ref * @return the t */ public static <T> T convertValue(@NonNull Object fromValue, @NonNull TypeReference<T> toValueTypeRef) { try { return objectMapper.convertValue(fromValue, toValueTypeRef); } catch (Exception e) { log.error("str2Obj fail"); return null; } } /** * 集合深拷贝 * * @param <T> the type parameter * @param src the src * @param dstClazz the dst clazz * @return the t */ public static <T> T deepCopy(Object src,TypeReference<T> dstClazz) { if (null == src) { return null; } return JsonUtils.str2Obj(JsonUtils.obj2Str(src), dstClazz); } }
总结一下
21年底的时候学习了一下Java8的新特性【Java新特性学习 四】JDK8: 库函数新特性之Optional,Streams,Date/Time API(JSR 310),Base64,并行数组,但同样只是大致了解了下,并未详细的使用和实验,如今发现工作中使用场景太多了,把这些常用的场景都记录下来,下次用的时候应该也比较方便了。