1、List分组

package com.fly.se.list;

import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 列表分组
 *
 * @author fly
 * @since 2023/4/21
 */
public class ListGroup {
	public static void main(String[] args) {
		List<Employee> employeeList = new ArrayList<>();
		employeeList.add(new Employee(1, "鸣人", 1, 17, 5000, new BigDecimal("62.35")));
		employeeList.add(new Employee(2, "佐助", 1, 17, 6000, new BigDecimal("62.35")));
		employeeList.add(new Employee(3, "小樱", 2, 17, 7000, new BigDecimal("52.35")));
		employeeList.add(new Employee(4, "小李", 1, 17, 8000, new BigDecimal("62.35")));
		employeeList.add(new Employee(5, "天天", 2, 17, 9000, new BigDecimal("52.35")));
		employeeList.add(new Employee(6, "路飞", 1, 18, 10000, new BigDecimal("62.35")));
		employeeList.add(new Employee(7, "索隆", 1, 18, 11000, new BigDecimal("62.35")));

		// 根据 年龄 分组
		Map<Object, List<Employee>> ageMap = employeeList.stream().collect(Collectors.groupingBy(Employee::getAge));

		//
		ageMap.forEach((age, list) -> {

		});

		// 先根据 性别 分组,再根据 年龄 分组
		Map<Integer, Map<Integer, List<Employee>>> sexAgeMap = employeeList.stream().collect(Collectors.groupingBy(Employee::getSex, Collectors.groupingBy(Employee::getAge)));
		sexAgeMap.forEach((sex, ageTmpMap) -> ageTmpMap.forEach((age, list) -> {

		}));

		// 先根据 性别 分组,再根据 姓名 分组,并将姓名放入Set
		Map<Integer, Set<String>> sexNameMap = employeeList.stream().collect(Collectors.groupingBy(Employee::getSex, Collectors.mapping(Employee::getName, Collectors.toSet())));
		sexNameMap.forEach((sex, nameTmpMap) -> nameTmpMap.forEach((name) -> {
		}));


		// 根据  传入参数  进行分组
		Map<String, List<Employee>> sexMap = employeeList.stream().collect(Collectors.groupingBy(e -> groupKey(e, "sex")));
		sexMap.forEach((sex, list) -> {

		});

		// 分组后,根据指定字段排序
		Map<Integer, List<Employee>> sexMap2 = employeeList.stream()
				.sorted(Comparator.comparing(Employee::getId,Comparator.nullsLast(Integer::compareTo)))
				.collect(Collectors.groupingBy(Employee::getSex, Collectors.toList()));
		sexMap2.forEach((sex, list) -> {

		});
	}

	@ApiOperation("list分组传参使用")
	private static <T> String groupKey(@ApiParam("实体类") T clazz,@ApiParam("字段名") String columnName) {
		try {
			// 获取指定字段的方法名
			String methodName = "get" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);
			// 获取指定字段的值
			Object value = clazz.getClass().getMethod(methodName).invoke(clazz);
			if (null != value) {
				return value.toString();
			}
		} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
			e.printStackTrace();
		}
		return "";
	}


	@Data
	@AllArgsConstructor
	static class Employee{
		@ApiModelProperty("主键id")
		private Integer id;

		@ApiModelProperty("姓名")
		private String name;

		@ApiModelProperty("性别 1:男 2:女 3:未知")
		private Integer sex;

		@ApiModelProperty("年龄")
		private Integer age;

		@ApiModelProperty("薪资")
		private Integer salary;

		@ApiModelProperty("体重")
		private BigDecimal weight;
	}
}
Java中,对`List`中的元素进行分组是一种常见的需求,尤其是在处理大量数据的时候。我们可以根据一定的规则将列表中的元素划分成若干个子集,每个子集中包含满足特定条件的数据项。以下是几种常用的实现方法: ### 使用Stream API和Collectors.groupingBy() 从Java 8开始引入了流式编程的概念,使得我们能够更方便地对集合进行操作,包括但不限于过滤、排序以及最重要的——分组。这里给出一个简单的例子来说明如何基于某个属性对列表里的对象做分组。 假设有一个存储学生信息的类`Student`,它有两个字段:名字(name)年级(grade),现在我们要按照学生的年级对他们进行分类: ```java import java.util.*; import java.util.stream.Collectors; class Student { private String name; private int grade; public Student(String name, int grade){ this.name = name; this.grade = grade; } // getter & setter omitted for brevity @Override public String toString(){ return name + ":" + grade; } } public class GroupByExample { public static void main(String[] args) { List<Student> students = Arrays.asList( new Student("Alice", 7), new Student("Bob", 6), new Student("Charlie", 7)); // 按照grade对学生进行分组 Map<Integer, List<Student>> groupedStudents = students.stream() .collect(Collectors.groupingBy(Student::getGrade)); // 打印结果 groupedStudents.forEach((grade, studentList) -> System.out.printf("Grade %d:%n%s%n", grade, studentList.toString())); } } ``` 上述代码首先创建了一个包含几个`Student`实例的列表,然后使用stream()函数将其转换为流形式;接着调用了`groupingBy()`收集器指定按`grade`属性来进行分组,并最终得到一个`Map<Integer, List<Student>>`类型的返回值表示各个年级的学生们组成的映射表。 ### 自定义逻辑实现 如果业务场景比较特殊,而现有的标准库提供的工具不足以解决问题的话,那么就不得不自己编写额外的功能了。这通常涉及到遍历整个list并对其中每一条记录都应用给定算法确定其所属类别。最后再把这些同类别的项目放到一起形成新的小清单。 ```java // 假设有个字符串数组需要分成长度相等的不同小组 ArrayList<ArrayList<String>> divideIntoGroups(List<String> items, int groupSize) { ArrayList<ArrayList<String>> groups = new ArrayList<>(); if (items == null || items.isEmpty()) { return groups; } int size = items.size(); for(int i = 0 ;i < size / groupSize +(size%groupSize==0 ? 0 :1); ++i ) { ArrayList<String> subgroup = new ArrayList<>(items.subList(i * groupSize , Math.min(size ,(i+1)*groupSize))); groups.add(subgroup); } return groups; } ``` 这段示例展示了怎样手动把一串文本依据固定的数目切割开来,当然实际运用时可以根据实际情况调整判断准则以适应更多元化的应用场景。 -- --相关问题--: 1. Java Streams 中除了 `groupingBy` 还有其他哪些有用的 Collector 工具吗? 2. 如果想根据多个属性同时对列表内容进行多重维度分组该如何操作呢? 3. 分组后的 Map 是否可以直接转回原始类型(如 List),如果是则应该如何去做? --- 希望以上介绍可以帮助您理解如何在Java程序里高效完成List分组任务。如果您有任何疑问或其他方面的问题都可以继续提问哦!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值