原创

java stream api实现mysql的groupby效果

1、需求

实现类似mysql的效果

select name,sex from user group by name,sex

2、实现的思路

目前的stream api的 Collectors.groupingBy可以实现分组的效果,但是返回的结果确实map,key分组的key,vaue为满足key条件的user对象。如果结果只需要name和sex字段。可以把这两个子弹作为key。然后只是保留key。

  • sex+name作为key,然后接收key后再拆分
  • 直接以新的对象为key,属性包括name和sex。获取后直接输出key就可以 了。

3、代码的实现方式

3.1、对象接收法

  • 定义一个对象,包含分组的key。其实也算输出的List对象

    @Test
    public void groupByTest1() {
        List<UserBean> userBeanList = createTestList();
        List<UserTempBean> result = StreamUtil.groupByField(userBeanList, UserTempBean.class);
        System.out.println(new Gson().toJson(result));
    }
    
    public class StreamUtil {
        public static <T> List<T> groupByField(List list, Class<T> clazz) {
            Object object =
                    list.stream()
                            .collect(
                                    Collectors.groupingBy(
                                            item -> {
                                                T t =
                                                        JacksonUtil.parse(
                                                                JacksonUtil.toJsonString(item), clazz);
                                                return t;
                                            }));
            if (null == object) {
                return null;
            }
            HashMap<T, Object> objectHashMap = (HashMap<T, Object>) object;
            if (null == objectHashMap || objectHashMap.isEmpty()) {
                return null;
            }
            List<T> result = objectHashMap.keySet().stream().collect(Collectors.toList());
            return result;
        }
    

3.2、见名知意法

  • 直接以可变参数的方式实现接口的定义
@Test
public void groupByTest() {
    List<UserBean> testList = createTestList();
    List<Map<String, Object>> maps = StreamUtil.groupByFileds(testList, "name", "age");
    System.out.println(JacksonUtil.toJsonString(maps));
}

public static List<Map<String, Object>> groupByFileds(List list, String... fields) {
        Object collect =
                list.stream()
                        .collect(
                                Collectors.groupingBy(
                                        item -> {
                                            Map parse =
                                                    JacksonUtil.parse(
                                                            JacksonUtil.toJsonString(item),
                                                            Map.class);
                                            if (null == parse || parse.isEmpty()) {
                                                return null;
                                            } else {
                                                Map<String, Object> map = Maps.newHashMap();
                                                for (String field : fields) {
                                                    map.put(field, parse.get(field));
                                                }
                                                return map;
                                            }
                                        }));
        if (null == collect) {
            return null;
        }
        Map<Map<String, Object>, Object> resultMap = (Map<Map<String, Object>, Object>) collect;
        if (null == resultMap || resultMap.isEmpty()) {
            return null;
        }
        return resultMap.keySet().stream().filter(Objects::nonNull).collect(Collectors.toList());
    }

4、扩展

  • 方法一巧妙的借用了json的序列化和反序列化
  • 方法二则是利用json反序列化和map的特性来解决问题

其实还有方式是在方案1的基础上来解决的。利用反射,性能不高,不推荐使用,仅作技术参考

@Test
public void reflecttionGetTest() throws IllegalAccessException {
    UserBean userBean = new UserBean("张三", 18, "男");
    Object name = ReflectionUtil.getObjectFieldValue(userBean, "name");
    System.out.println(name);
    Object object = ReflectionUtil.updateObjectField(userBean, "name", "诸葛亮");
    System.out.println(JacksonUtil.toJsonString(object));
}
package net.gzcx;
import com.google.common.collect.Lists;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Optional;

/**
 * @author chen xing
 * @description 反射工具类
 * @date 2022-06-23 20:18
 */
public class ReflectionUtil {
    /**
     * @author chen xing
     * @description 设置指定对象的属性值
     * @param object
     * @param fieldName
     * @param fieldValue
     * @return void
     * @date 2022-06-23 20:21
     */
    public static Object updateObjectField(Object object, String fieldName, String fieldValue)
            throws IllegalAccessException {
        Class objectClass = object.getClass();

        Field[] declareFileds = objectClass.getDeclaredFields();
        if (null == declareFileds || declareFileds.length == 0) {
            return object;
        }
        for (Field field : declareFileds) {
            String name = field.getName();
            if (fieldName.equals(name)) {
                field.setAccessible(true);
                field.set(object, fieldValue);
                break;
            }
        }
        return object;
    }

    /**
     * @author chen xing
     * @description 获取指定对象的指定的内容
     * @param object
     * @param fieldName
     * @return java.lang.Object
     * @date 2022-06-23 20:22
     */
    public static Object getObjectFieldValue(Object object, String fieldName)
            throws IllegalAccessException {
        // 获取对象的class
        Class objectClass = object.getClass();
        // 初始化该值
        Object result = null;

        Field[] declaredFields = objectClass.getDeclaredFields();
        if (null == declaredFields || declaredFields.length == 0) {
            return null;
        }
        for (Field field : declaredFields) {
            String name = field.getName();
            if (fieldName.equals(name)) {
                field.setAccessible(true);
                result = field.get(object);
                break;
            }
        }
        return result;
    }
}
正文到此结束
本文目录