集合批量移动元素
需求:某1196高校要举办一个不知其名的活动,随机选了几个班级的某几个学生参加活动,学生到指定地点后,要对学生的座位号进行调整。前提学生本身有自己的座位号,同一个班级的座位号需要从小到大的坐,要求在调整座位号的时候,同一个班的学生必须坐在一起。
分析
其实这就是一个集合元素的移动,同一个班级的学生要求坐在一起其实就是根据对象某个属性进行【合并】的操作,前后调整座位号的时候,当向前调整的时候,如果座位号小于前一个班级的最大的座位号;当先后调整的时候,如果座位号大于后一个班级最小的座位号,那么前后两个班级的座位号需要整体互换。同一个班级的前后座位号的人对调位置即可。其实仔细想这不就是带合并单元格的表格选中几行上下移动吗?
代码实现
package entity;
/**
* @description: 学生信息
* @author: pks
* @date: 2024/7/14 19:26
*/
public class Student {
/**
* ID
*/
private Integer id;
/**
* 姓名
*/
private String name;
/**
* 班级
*/
private String classGrades;
/**
* 省
*/
private String province;
/**
* 市
*/
private String city;
/**
* 县
*/
private String county;
/**
* 详细地址
*/
private String address;
/**
* 生日
*/
private String birthday;
/**
* 座位号
*/
private Integer seatNumber;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassGrades() {
return classGrades;
}
public void setClassGrades(String classGrades) {
this.classGrades = classGrades;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCounty() {
return county;
}
public void setCounty(String county) {
this.county = county;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public Integer getSeatNumber() {
return seatNumber;
}
public void setSeatNumber(Integer seatNumber) {
this.seatNumber = seatNumber;
}
}
package util;
import entity.Student;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Stack;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @description: 移动排序
* @author: pks
* @date: 2024/7/14 19:34
*/
public class SortUtils {
/**
* 前移
*/
public static final String FRONT_DIRECTION = "front";
/**
* 后移
*/
public static final String REAR_DIRECTION = "rear";
/**
* 学生座位移动
*
* @param moveDirection 移动方向 front or rear
* @param studentList 所有学生
* @param moveStudentList 移动座位的学生
* @return 移动后排序的学生
*/
public static List<Student> moveStudent(String moveDirection, List<Student> studentList, List<Student> moveStudentList) {
List<Student> result = new ArrayList<>();
// 所有学生大于等于2时才有移动座位的必要
if (moveStudentList == null || studentList.size() < 2) {
return studentList;
}
// 学生按照班级分组
Map<String, List<Student>> studentsMap = studentList.stream().collect(Collectors.groupingBy(Student::getClassGrades));
// 学生最终的排序,按照同一班级里面最小的序号再进行排序
List<Student> lastSortStudents = getMinNumberStudents(studentsMap);
Map<String, Integer> sortClassGradesMap = new HashMap<>(); // 按照班级整体排序
Map<Integer, String> reverseSortClassGradesMap = new HashMap<>(); // 班级学生整体排序key,value互换
Integer wholeSort = 1;
for (Student lastSortStudent : lastSortStudents) {
sortClassGradesMap.put(lastSortStudent.getClassGrades(), wholeSort);
reverseSortClassGradesMap.put(wholeSort, lastSortStudent.getClassGrades());
wholeSort ++;
}
for (Student moveStudent : moveStudentList) {
List<Student> students = studentsMap.get(moveStudent.getClassGrades());
// 前移比较最小值
Student minSortStudent = students.stream()
.min(Comparator.comparing(Student::getSeatNumber)).orElse(null);
// 后移比较最大值
Student maxSortStudent = students.stream()
.max(Comparator.comparing(Student::getSeatNumber)).orElse(null);
Integer seatNumber = moveStudent.getSeatNumber();
// 当前批量项目整体序号
Integer currentBatchSort = sortClassGradesMap.get(moveStudent.getClassGrades());
if (FRONT_DIRECTION.equals(moveDirection)) {
seatNumber = seatNumber - 1;
if (minSortStudent != null && seatNumber < minSortStudent.getSeatNumber()) {
// 前一个班级整体序号
Integer preBatchSort = currentBatchSort - 1;
String preClassGrades = reverseSortClassGradesMap.get(preBatchSort);
sortClassGradesMap.put(moveStudent.getClassGrades(), preBatchSort);
reverseSortClassGradesMap.put(preBatchSort, moveStudent.getClassGrades());
sortClassGradesMap.put(preClassGrades, currentBatchSort);
reverseSortClassGradesMap.put(currentBatchSort, preClassGrades);
}
}
if (REAR_DIRECTION.equals(moveDirection)) {
seatNumber = seatNumber + 1;
if (maxSortStudent != null && seatNumber > maxSortStudent.getSeatNumber()) {
// 后一个班级的整体序号
Integer nextBatchSort = currentBatchSort + 1;
String nextClassGrades = reverseSortClassGradesMap.get(nextBatchSort);
sortClassGradesMap.put(moveStudent.getClassGrades(), nextBatchSort);
reverseSortClassGradesMap.put(nextBatchSort, moveStudent.getClassGrades());
sortClassGradesMap.put(nextClassGrades, currentBatchSort);
reverseSortClassGradesMap.put(currentBatchSort, nextClassGrades);
}
}
// 利用堆栈对学生排序
students = stackSortStudent(students, moveStudent, moveDirection);
studentsMap.put(moveStudent.getClassGrades(), students);
}
for (int i = 1; i <= lastSortStudents.size(); i ++) {
String projectName = reverseSortClassGradesMap.get(i);
result.addAll(studentsMap.get(projectName));
}
return result;
}
private static List<Student> getMinNumberStudents(Map<String, List<Student>> studentsMap) {
List<Student> sortStudents = new ArrayList<>();
// 同一个班级里面座位最小的学生
for (List<Student> value : studentsMap.values()) {
if (value == null || value.size() == 0) {
continue;
}
Student minSortStudent = value.stream()
.min(Comparator.comparing(Student::getSeatNumber)).orElse(null);
sortStudents.add(minSortStudent);
}
// 学生最终的排序,按照同班级学生里面座位号最小的学生再进行排序
return sortStudents.stream()
.sorted(Comparator.comparing(Student::getSeatNumber, Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());
}
/**
* 学生重新排序
*
* @param students 学生集合
* @param moveStudent 移动学生
* @param moveDirection 移动方向
* @return 移动后重新排序学生
*/
public static List<Student> stackSortStudent(List<Student> students, Student moveStudent, String moveDirection) {
Stack<Student> studentStack = new Stack<>();
Queue<Student> studentQueue = new LinkedList<>(students);
while (studentStack.size() < students.size()) {
Student poll = studentQueue.poll();
if (poll == null) {
continue;
}
if (poll.getId().equals(moveStudent.getId())) {
if (FRONT_DIRECTION.equals(moveDirection)) {
if (!studentStack.isEmpty()) {
// 上移先进的元素取出放在当前元素后面
Student pop = studentStack.pop();
studentStack.push(poll);
studentStack.push(pop);
} else {
studentStack.push(poll);
}
}
if (REAR_DIRECTION.equals(moveDirection)) {
Student next = studentQueue.poll();
// 下移将下一个元素先放进栈
if (next != null) {
studentStack.push(next);
}
studentStack.push(poll);
}
} else {
studentStack.push(poll);
}
}
return new LinkedList<>(studentStack);
}
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
for (int i = 0; i < 20; i++) {
Student student = new Student();
student.setId(i);
student.setSeatNumber(i);
student.setName("student" + i);
if (i < 6) {
student.setClassGrades("666班");
} else if (i < 12) {
student.setClassGrades("888班");
} else {
student.setClassGrades("999班");
}
students.add(student);
}
for (Student student : students) {
System.out.println(student.getClassGrades() + " : " + student.getName() + ":" + student.getSeatNumber());
}
System.out.println("***************************重新调整座位号************************************");
Map<Integer, Student> studentMap = students.stream().collect(Collectors.toMap(Student::getId, Function.identity()));
List<Student> sortStudents = moveStudent(REAR_DIRECTION, students, Arrays.asList(studentMap.get(5), studentMap.get(12)));
for(int i = 0; i < sortStudents.size();i ++) {
sortStudents.get(i).setSeatNumber(i);
}
for (Student student : sortStudents) {
System.out.println(student.getClassGrades() + " : " + student.getName() + ":" + student.getSeatNumber());
}
}
}