精华内容
下载资源
问答
  • user .stream().collect(Collectors.summingInt(User::getAge))参数类型:summarizingDouble 统计数据(double)状态, 其中包括count min max sum和平均值summarizingInt 统计数据(int)状态, 其中包括count min max ...

    集合:

    List user = new User();

    user .stream().collect(Collectors.summingInt(User::getAge))

    参数类型:

    summarizingDouble 统计数据(double)状态, 其中包括count min max sum和平均值

    summarizingInt 统计数据(int)状态, 其中包括count min max sum和平均值

    summarizingLong 统计数据(long)状态, 其中包括count min max sum和平均值.

    summingInt 求和 返回int类型

    summingDouble 求和 返回double类型

    summingLong 求和 返回long类型

    counting 返回Stream的元素个数

    averagingDouble 求平均值 返回double类型

    averagingInt 求平均值 返回int类型

    averagingLong 求平均值 返回long类型

    maxBy 在指定条件下,返回最大值

    minBy 在指定条件下,返回最小值

    补充知识:Java8集合List排序、筛选、求和、求最大值、平均值、List转Map

    Java8集合List排序、筛选

    1. List

    元素有序

    元素可重复

    1.1 ArrayList

    动态数组实现

    查询快

    增删慢(末尾处也快)

    1.2 LinkedList

    链表实现

    查询慢

    增删快

    1.3 ArrayList和LinkedList比较

    实现

    查询

    增删

    线程安全?

    ArrayList

    动态数组

    慢(末尾处也快)

    不安全

    LinkedList

    链表

    不安全

    ArrayList:

    它的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍。

    LinkedList:

    底层实现是双向链表。

    在增加和删除元素时效率较高。

    1.4 List过滤指定元素

    1.4.1 准备待测试的List

    public class Message {

    private Long id; //id

    private String msg; //消息

    private Date sendTime; //时间戳

    //省略get set

    }

    //返回一个List

    private static List getMessageList(){

    List list = new ArrayList<>();

    list.add(new Message(1L, "a", new Date()));

    list.add(new Message(2L, "b", new Date()));

    list.add(new Message(4L, "b", new Date()));

    list.add(new Message(3L, "c", new Date()));

    return list;

    }

    1.4.2 使用Iterator遍历List

    private static void TestArrayList(){

    List list = getMessageList();

    System.out.print("删除前:");

    list.stream().forEach(item -> System.out.print(item));

    Iterator it = list.iterator();

    while (it.hasNext()) {

    Message s = it.next();

    if (s.getMsg().equals("b")) {

    it.remove();

    }

    }

    System.out.print("

    删除后:");

    list.stream().forEach(item -> System.out.print(item));

    }

    1.4.2 使用Java8对List过滤筛选

    private static void filterList(){

    List list1 = getMessageList();

    //过滤所有msg是b的记录

    List list2 = list1.stream().filter(s -> !s.getMsg().equals("b")).collect(Collectors.toList());

    list2.stream().forEach(item -> System.out.println(item));

    }

    1.4.3 使用distinct去重

    //使用distinct去重

    List distinctMsg = list.stream().map(Message::getMsg).distinct().collect(Collectors.toList());

    distinctMsg.forEach(System.out::println);

    1.4.4 使用toSet去重

    //使用collect(toSet())去重

    Set distinctMsg2 = list.stream().map(Message::getMsg).collect(toSet());

    distinctMsg2.forEach(System.out::println);

    1.5 使用Java8对List排序

    1.5.1 单个字段排序

    private static void sortList(){

    List list = getMessageList();

    if (list != null && !list.isEmpty()){

    System.out.println("===排序前如下===");

    list.stream().forEach(item -> System.out.println(item));

    //根据Id升序排序

    list.sort((a, b) -> a.getId().compareTo(b.getId()));

    //根据Id升序排序(简写)

    list.sort(Comparator.comparing(Message::getId));

    //根据Id降序排序(简写)

    list.sort(Comparator.comparing(Message::getId).reversed());

    System.out.println("===排序后如下===");

    list.stream().forEach(item -> System.out.println(item));

    }

    }

    1.5.2 多个字段组合排序

    private static void sortList(){

    List list = getMessageList();

    if (list != null && !list.isEmpty()){

    System.out.println("===排序前如下===");

    list.stream().forEach(item -> System.out.println(item));

    //根据多条件组合排序,先根据msg(升序),再根据id(升序)

    list.sort(Comparator.comparing(Message:: getMsg).thenComparing(Message::getId));

    //根据多条件组合排序,先根据msg(升序),再根据id(降序)

    list.sort(Comparator.comparing(Message:: getMsg).thenComparing(Comparator.comparing(Message::getId).reversed()));

    //根据多条件组合排序,先根据msg(降序),再根据id(降序)

    list.sort(Comparator.comparing(Message:: getMsg).thenComparing(Message::getId).reversed());

    //根据多条件组合排序,先根据msg(降序),再根据id(升序)

    list.sort(Comparator.comparing(Message:: getMsg).reversed().thenComparing(Message::getId));

    System.out.println("===排序后如下===");

    list.stream().forEach(item -> System.out.println(item));

    }

    }

    1.6 List转List

    List idList =

    list.stream().map(Message::getId).collect(Collectors.toList());

    1.6.1 List转List +去重

    //利用distinct()

    List msgList =

    list.stream().map(Message::getMsg).distinct().collect(Collectors.toList());

    //利用Collectors.toSet()

    Set msgList2 =

    list.stream().map(Message::getMsg).collect(Collectors.toSet());

    1.7 List转Map

    还是上面的测试数据,按Message的msg作为key,如果key重复就用第一个.

    private static void listToMap(){

    List list = getMessageList();

    Map map =

    list.stream().collect(Collectors.toMap(Message :: getMsg, a-> a, (k1, k2) -> k1));

    System.out.println(map.size());

    }

    原本List有4个元素,因为有2条msg="b"的数据,转map后取第一条

    54d62027380ed4d953f85f1a6d660095.png

    1.7.1 forEach遍历Map

    map.forEach((k,v) -> {

    System.out.println(k + " -> " + v);

    });

    1.8 List转Map>

    Map> groupByMsg = list.stream().collect(groupingBy(Message::getMsg));

    groupByMsg.forEach((k, v) -> {

    System.out.println(k + " -> " + v.toString());

    });

    返回如下:

    a -> [Message(id=1, msg=a, sendTime=Fri May 15 17:36:30 CST 2020)]

    b -> [Message(id=2, msg=b, sendTime=Fri May 15 17:36:30 CST 2020), Message(id=4, msg=b, sendTime=Fri May 15 17:36:30 CST 2020)]

    c -> [Message(id=3, msg=c, sendTime=Fri May 15 17:36:30 CST 2020)]

    1.9 List>转Map>>

    Map>> groupByGenderMap =

    pigMapList.stream().collect(groupingBy(e -> e.get("gender").toString()));

    1.10 List求和、求最大值、平均值

    private static void statisticsList(){

    List list = getMessageList();

    //求和

    Long sum= list.stream().mapToLong(Message::getId).sum();

    System.out.println("sum = " + sum);

    //求最大值

    Optional maxMassage = list.stream().collect(Collectors.maxBy(Comparator.comparing(Message::getId)));

    Long maxId = maxMassage.get().getId();

    System.out.println("maxId = " + maxId);

    LongSummaryStatistics lss = list.stream().collect(Collectors.summarizingLong(Message::getId));

    System.out.println("sum = " + lss.getSum());

    System.out.println("max = " + lss.getMax());

    System.out.println("min = " + lss.getMin());

    System.out.println("avg = " + lss.getAverage());

    }

    以上这篇java8实现list集合中按照某一个值相加求和,平均值等操作代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持云海天教程。

    原文链接:https://blog.csdn.net/F_Z_S/article/details/103510180

    展开全文
  • 对集合数据的统计,是开发中常用的功能,掌握好Java Stream提供的方法,避免自己写代码统计,可以提高工作效率。 先造点数据: pigs.add(new Pig(1, "猪爸爸", 31, "M", false)); pigs.add(new Pig(2, "猪妈妈", 28,...

    对集合数据的统计,是开发中常用的功能,掌握好Java Stream提供的方法,避免自己写代码统计,可以提高工作效率。

    先造点数据:

    pigs.add(new Pig(1, "猪爸爸", 31, "M", false));
    pigs.add(new Pig(2, "猪妈妈", 28, "F", true));
    pigs.add(new Pig(3, "乔治", 2, "M", false));
    pigs.add(new Pig(4, "佩奇", 5, "F", false));
    

    一、统计个数

    用Stream流中的count()函数可以方便的获取元素个数。

    long count = pigs.stream().filter(a -> a.getAge() > 5).count();
    System.out.println("age > 5的人数 = " + count);
    

    二、利用数值流自带的函数

    如果是数值流,可以利用它自带的sum、max、min、average这些函数。

    流用一次就不能用第二次,每次都得重新创建流。

    long count = pigs.stream().mapToInt(Pig::getAge).count();
    int sumAge = pigs.stream().mapToInt(Pig::getAge).sum();
    int maxAge = pigs.stream().mapToInt(Pig::getAge).max().getAsInt();
    int minAge = pigs.stream().mapToInt(Pig::getAge).min().getAsInt();
    double avgAge = pigs.stream().mapToInt(Pig::getAge).average().getAsDouble();
    

    三、summaryStatistics统计

    流用一次就不能用第二次,可以一次性获取一个流的所有统计信息。

    IntSummaryStatistics statistics = pigs.stream().mapToInt(Pig::getAge).summaryStatistics();
    
    System.out.println("count = " + statistics.getCount());
    System.out.println("sumAge = " + statistics.getSum());
    System.out.println("maxAge = " + statistics.getMax());
    System.out.println("minAge = " + statistics.getMin());
    System.out.println("avgAge = " + statistics.getAverage());
    

    四、利用Collectors

    1. 对象流

    如果是对象流,想求某个值最大的对象,可以用Collectors

    例如:求age最大的猪对象,age最小的猪对象

    Optional<Pig> pigMaxAgeOptional = pigs.stream().collect(Collectors.maxBy(comparing(Pig::getAge)));
    if (pigMaxAgeOptional.isPresent()){
        System.out.println("age最大的猪 = " + pigMaxAgeOptional.get());
    }
    
    Optional<Pig> pigMinAgeOptional = pigs.stream().collect(Collectors.minBy(comparing(Pig::getAge)));
    if (pigMinAgeOptional.isPresent()){
        System.out.println("age最小的猪 = " + pigMinAgeOptional.get());
    }
    

    结果如下:

    age最大的猪 = Pig(id=1, name=猪爸爸, age=31, gender=M, valid=false)
    age最小的猪 = Pig(id=3, name=乔治, age=2, gender=M, valid=false)
    

    2. 数值流

    Collections还提高了max、min

    Set<Integer> ageSet = pigs.stream().map(Pig::getAge).collect(Collectors.toSet());
    
    System.out.println("maxAge=" + Collections.max(ageSet));
    System.out.println("minAge=" + Collections.min(ageSet));
    
    展开全文
  • Java8新特性Stream流api实用的一些封装

    热门讨论 2021-03-24 11:21:15
    单字段排序多字段排序排序测试从List中查找最大/最小值的元素测试合并List中某个属性值, 计算 总数/平均数测试List统计数据测试List转换为Map如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个...

    在某些业务场景中, 我们经常会对集合中的数据进行处理, Java8 提供了 Stream API 可以让我们很方便地处理集合中的数据, 例如, 分组, 过滤, 排序等, 但是每次处理数据的时候都要开流去处理, 所以我们可以对stream api进行一些简单的封装, 这样的话一些通用场景下就不需要写重复的逻辑了.

    功能介绍

    经过一阵子的努力, 我简单的封装了一个工具类, 目前工具类中功能大概有以下几个:

    1. List分组, 可以整合分组后的结果, 例如根据dept对user进行分组后, value整合为user的分数之类的.
    2. List排序, 单字段 / 多字段排序.
    3. List根据字段寻找最小值 / 最大值 元素.
    4. List中某个对象的值合并, 例如求某个字段的总和 / 平均值
    5. List某个字段统计数据获取(最小值, 最大值, 平均值, 总和等)
    6. List转Map
    7. Map的排序, 可以根据key / value进行排序
    8. List转换为其他集合, 数组转换为集合.
    9. List根据某个字段去重.

    List分组

    根据字段简单分组

    首先先准备两个函数, 用于判空, 一切都是从这两个函数开始的.

    /**
         * list判空
         *
         * @param list 集合
         */
        private static void notEmptyCondition(List<?> list) {
            if (list == null || list.size() == 0) throw new NullPointerException("这就有点不讲武德了, 给我个空我怎么处理呢.");
        }
    
        /**
         * map 判空
         *
         * @param map map集合
         */
        private static void notEmptyCondition(Map<?, ?> map) {
            if (map == null || map.entrySet().size() == 0) throw new NullPointerException("这就有点不讲武德了, 给我个空我怎么处理呢.");
        }
    

    接着准备分组函数

    /**
         * 简单分组
         *
         * @param list       集合
         * @param classifier 分组字段选择函数
         * @param <T>        输入类型
         * @param <K>        Key的类型
         * @return 最后返回Map<K, List < T>
         */
        public static <T, K> Map<K, List<T>> simpleGroupingBy(List<T> list, Function<? super T, ? extends K> classifier) {
            notEmptyCondition(list);
            return list.stream().collect(Collectors.groupingBy(classifier));
        }
    

    对分组后的结果进行排序

    1. 首先准备排序函数
    /**
         * 基本排序操作, 这里约定了排序字段的选择必须是实现了Comparable接口的.
         *
         * @param list      集合
         * @param desc      是否降序
         * @param keySelect 排序字段选择函数
         * @param <T>       输入类型
         */
        private static <T, U extends Comparable<U>> void sortList
        (
                List<T> list, boolean desc, Function<? super T, ? extends U> keySelect
        ) {
        	// 这里如果是降序的话, 就将List进行反转
            if (desc) {
                list.sort(Comparator.comparing(keySelect));
                Collections.reverse(list); //反转List
            } else {
                list.sort(Comparator.comparing(keySelect));
            }
        }
    
    1. 分组函数, 和上一个没什么区别, 就是多了个排序.
    /**
         * 简单分组 + 排序字段的选择
         *
         * @param list       集合
         * @param classifier 分组字段
         * @param keySelect  排序字段选择
         * @param desc       是否降序
         * @param <T>        输入类型
         * @param <K>        key的类型
         * @return 最后返回Map<K, List < T> List为排序之后的List
         */
        public static <T, K, C extends Comparable<C>> Map<K, List<T>> simpleGroupingBy
        (
                List<T> list, Function<? super T, ? extends K> classifier, boolean desc,
                Function<? super T, ? extends C> keySelect
        ) {
            notEmptyCondition(list);
            sortList(list, desc, keySelect);
            return list.stream().collect(Collectors.groupingBy(classifier));
        }
    

    简单分组测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    		//根据TestUser的DeptId进行分组, 这里返回的Key为DeptId, value为List<TestUser>
            Map<Long, List<TestUser>> result = FunctionalUtil.simpleGroupingBy(list, TestUser::getDeptId);
            System.err.println("result = " + result);
    		
    		//根据TestUser的DeptId进行分组, 并对List进行排序, 排序字段为TestUser的winningCount字段
            Map<Long, List<TestUser>> result2 = FunctionalUtil.simpleGroupingBy(list, TestUser::getDeptId, true, TestUser::getWinningCount);
            System.err.println("result2 = " + result2);
    }
    

    控制台打印的结果:

    result = {1=[TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}, TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}], 2=[TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}, TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}]}
    result2 = {1=[TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}, TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}], 2=[TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}, TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}]}
    

    选择返回字段分组

    在分组后从对象中选取字段进行返回

    /**
         * 可选返回字段函数式分组
         *
         * @param list            列表
         * @param classifier      分组字段选择
         * @param mappingFunction 返回字段
         * @param <T>             输入类型
         * @param <K>             key类型
         * @param <U>             最后返回的元素类型
         * @return 最后返回Map<K, List < U>
         */
        public static <T, K, U> Map<K, List<U>> customizingFieldGroupingBy
        (
                List<T> list, Function<? super T, ? extends K> classifier,
                Function<? super T, ? extends U> mappingFunction
        ) {
            notEmptyCondition(list);
            return list.stream()
                    .collect(Collectors.groupingBy(classifier, Collectors.mapping(mappingFunction, Collectors.toList())));
        }
    

    排序结果: 和上面用的排序函数一致.

    /**
         * 可选返回字段函数式分组 + 排序字段选择
         *
         * @param list            列表
         * @param classifier      分组字段选择
         * @param mappingFunction 返回字段
         * @param keySelect       排序字段选择
         * @param desc            是否降序
         * @param <T>             输入类型
         * @param <K>             key类型
         * @param <U>             最后返回的元素类型
         * @return 最后返回Map<K, List < U>
         */
        public static <T, K, U, C extends Comparable<C>> Map<K, List<U>> customizingFieldGroupingBy
        (
                List<T> list, Function<? super T, ? extends K> classifier,
                Function<? super T, ? extends U> mappingFunction, boolean desc,
                Function<? super T, ? extends C> keySelect
        ) {
            notEmptyCondition(list);
            sortList(list, desc, keySelect);
            return list.stream()
                    .collect(Collectors.groupingBy(classifier, Collectors.mapping(mappingFunction, Collectors.toList())));
        }
    

    选择返回字段分组测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    
    		//根据deptId字段进行分组, 选择score字段进行返回
            Map<Long, List<Double>> resultMap = FunctionalUtil.customizingFieldGroupingBy(list, TestUser::getDeptId, TestUser::getScore);
            System.err.println("resultMap = " + resultMap);
    		
    		//根据deptId字段进行分组, 选择score字段进行返回, 按照score降序进行排序
            Map<Long, List<Double>> resultMap2 = FunctionalUtil.customizingFieldGroupingBy(list, TestUser::getDeptId, TestUser::getScore, true, TestUser::getScore);
            System.err.println("resultMap2 = " + resultMap2);
    }
    

    控制台打印的结果:

    resultMap = {1=[120.0, 110.0], 2=[130.0, 150.0]}
    resultMap2 = {1=[120.0, 110.0], 2=[150.0, 130.0]}
    

    合并结果集分组

    最后返回Map<K, Double>, 将对象的某个值进行合并操作, 求和/求平均值操作.

    1. 准备枚举MergingOperation
    /**
     * @author nathan
     * @date 3/23/2021 9:34 AM
     * @description: 合并操作符
     */
    public enum MergingOperation {
    
        // 相加   求平均值
        SUMMING, AVERAGING
    }
    
    1. 函数
    /**
         * 分组后合并操作
         *
         * @param list              集合List
         * @param classifier        分组字段
         * @param mergingClassifier 合并字段选择, 支持多字段选择, 限制只能是数字 Integer/Long/Double
         * @param <T>               输入类型
         * @param <K>               key类型
         * @return Map<Long, ? extends Number>
         */
        @SafeVarargs
        public static <T, K> Map<K, Double> mergingResultGroupingBy
        (
                List<T> list, Function<? super T, ? extends K> classifier, MergingOperation mergingOperation,
                Function<? super T, ? extends Number>... mergingClassifier
        ) {
            notEmptyCondition(list);
            return mergingGroupingBy(list, classifier, mergingOperation, mergingClassifier);
        }
    
    /**
         * 合并操作, 分组后计算总值/平均值
         *
         * @param list              集合
         * @param classifier        分组字段选择
         * @param mergingClassifier 不定长参数, 选择多个合并字段.
         * @param mergingOperation  合并操作符
         * @param <T>               输入类型
         * @param <K>               key类型
         * @return 合并结果
         */
        @SafeVarargs
        private static <T, K> Map<K, Double> mergingGroupingBy
        (
                List<T> list, Function<? super T, ? extends K> classifier,
                MergingOperation mergingOperation, Function<? super T, ? extends Number>... mergingClassifier
        ) {
            switch (mergingOperation) {
            	//求总和
                case SUMMING:
                    return list.stream()
                            .collect(Collectors.groupingBy(classifier, Collectors.summingDouble(s -> {
                            	//这里的逻辑是这样的, 循环多个函数相加出总和进行合并
                                double sum = 0;
                                for (Function<? super T, ? extends Number> function : mergingClassifier) {
                                    sum += function.apply(s).doubleValue();
                                }
                                return sum;
                            })));
    			//求平均值
                case AVERAGING:
                    return list.stream().collect(Collectors.groupingBy(classifier, Collectors.averagingDouble(s -> {
                    	//循环多个函数, 计算出总和后求平均值
                        double sum = 0;
                        for (Function<? super T, ? extends Number> function : mergingClassifier) {
                            sum += function.apply(s).doubleValue();
                        }
                        return sum;
                    })));
                default:
                    return null;
            }
        }
    

    合并结果集分组测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    
            // 根据deptId进行分组后, 将count 和 winningCount进行求和
            Map<Long, Double> resultMap = FunctionalUtil.mergingResultGroupingBy
                    (
                            list, TestUser::getDeptId, MergingOperation.SUMMING,
                            //不定长参数, 因此可以传多个: Function<? super T, ? extends Number>... mergingClassifier
                            //但是只能传数字, 其他类型的话会飘红, 比如TestUser::getUsername
                            TestUser::getCount, TestUser::getWinningCount
                    );
    
            System.err.println("resultMap = " + resultMap);
    
            // 根据deptId进行分组后, 将count 和 winningCount进行求和后计算平均值
            Map<Long, Double> resultMap2 = FunctionalUtil.mergingResultGroupingBy
                    (
                            list, TestUser::getDeptId, MergingOperation.AVERAGING,
                            //不定长参数, 因此可以传多个: Function<? super T, ? extends Number>... mergingClassifier
                            //但是只能传数字, 其他类型的话会飘红, 比如TestUser::getUsername
                            TestUser::getCount, TestUser::getWinningCount
                    );
    
            System.err.println("resultMap2 = " + resultMap2);
    }
    

    控制台打印的结果:

    resultMap = {1=63.0, 2=247.0}
    resultMap2 = {1=31.5, 2=123.5}
    

    分组后对结果集进行处理

    /**
         * 分组后自定义结果集
         *
         * @param list             集合
         * @param classifier       分组字段
         * @param finisherFunction 整合函数, 传入一个函数函数的参数为Map<K, List<T>, 返回值为泛型R
         * @param <T>              集合内元素类型
         * @param <K>              Key类型
         * @param <R>              返回值
         * @return R
         * <p>
         * example:
         * int function(Map<K, List<T>);
         * customizingResultSetGroupingBy(list, Obj::getField, this::function);
         */
        public static <T, K, R> R customizingResultSetGroupingBy
        (
                List<T> list,
                Function<? super T, ? extends K> classifier,
                Function<Map<K, List<T>>, R> finisherFunction
        ) {
            notEmptyCondition(list);
            return list.stream().collect(Collectors.collectingAndThen(Collectors.groupingBy(classifier), finisherFunction));
        }
    

    测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
            Main main = new Main();
            main.test(list);
        }
        
        public void test(List<TestUser> testUserList) {
        	// 分组后的结果使用finisher方法处理, 返回的结果由finisher方法决定
            Double result = FunctionalUtil.customizingResultSetGroupingBy(testUserList, TestUser::getDeptId, this::finisher);
            System.err.println(result); //控制台打印: 0.0
        }
    
        private double finisher(Map<Long, List<TestUser>> map) {
            //对Map进行处理的逻辑....
            return 0;
        }
    

    分组后统计每组的数量

    /**
         * 分组后统计分组后的数量
         *
         * @param list       list集合
         * @param classifier 分组字段
         * @param <T>        输入类型
         * @param <K>        Key类型
         * @return Map<K, Long> Long为每组的数量
         */
        public static <T, K> Map<K, Long> countListGroupingBy(List<T> list, Function<? super T, ? extends K> classifier) {
            notEmptyCondition(list);
            return list.stream().collect(Collectors.groupingBy(classifier, Collectors.counting()));
        }
    

    测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    
            Map<Long, Long> result = FunctionalUtil.countListGroupingBy(list, TestUser::getDeptId);
            System.err.println("result = " + result);
        }
    

    控制台打印结果:

    result = {1=2, 2=2}
    

    对List的操作

    List的排序

    1. 单字段排序

    /**
         * 根据单个字段进行排序, 排序对象可以是实现了Comparable接口的对象
         *
         * @param list      集合
         * @param keySelect 字段选择
         * @param desc      true: 降序, false: 升序
         * @param <T>       输入类型
         */
        public static <T, U extends Comparable<U>> void sort
        (
                List<T> list, boolean desc, Function<? super T, ? extends U> keySelect
        ) {
            notEmptyCondition(list);
            sortList(list, desc, keySelect);
        }
    /**
         * 基本排序操作, 这里约定了排序字段的选择必须是实现了Comparable接口的.
         *
         * @param list      集合
         * @param desc      是否降序
         * @param keySelect 排序字段选择函数
         * @param <T>       输入类型
         */
        private static <T, U extends Comparable<U>> void sortList
        (
                List<T> list, boolean desc, Function<? super T, ? extends U> keySelect
        ) {
        	// 这里如果是降序的话, 就将List进行反转
            if (desc) {
                list.sort(Comparator.comparing(keySelect));
                Collections.reverse(list); //反转List
            } else {
                list.sort(Comparator.comparing(keySelect));
            }
        }
    

    多字段排序

    /**
         * 根据多个字段进行排序, 排序字段的选择必须为数字, 排序方式为, 字段1 + 字段2 + 字段... 总和进行排序
         *
         * @param list      list集合
         * @param desc      是否降序
         * @param keySelect 字段选择
         * @param <T>       输入类型
         */
        @SafeVarargs
        public static <T> void sort(List<T> list, boolean desc, Function<? super T, ? extends Number>... keySelect) {
            notEmptyCondition(list);
            sortList(list, desc, keySelect);
        }
    
    /**
         * 精准排序, 限制数字类型, 支持多字段排序, 多字段排序为多个字段的总和后进行排序, 泛型约定了只能为数字.
         *
         * @param list      list集合
         * @param desc      是否降序
         * @param keySelect 排序字段选择, 不定长参数可以选择多个字段进行排序
         * @param <T>       输入类型
         */
        @SafeVarargs
        private static <T> void sortList(List<T> list, boolean desc, Function<? super T, ? extends Number>... keySelect) {
            list.sort(Comparator.comparingDouble(s -> {
                double sum = 0;
                for (Function<? super T, ? extends Number> function : keySelect) {
                    sum += function.apply(s).doubleValue();
                }
                return desc ? -(sum) : sum;
            }));
        }
    

    排序测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    
            // 根据winningCount降序进行排序
            FunctionalUtil.sort(list, true, TestUser::getWinningCount);
    
            System.err.println("winningCount降序排序: " + list);
    
            // 根据score和count降序进行排序
            FunctionalUtil.sort(list, true, TestUser::getScore, TestUser::getCount);
            System.err.println("score和Count降序排序: " + list);
        }
    

    控制台打印的结果:

    winningCount降序排序: [TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}, TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}, TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}, TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}]
    score和Count降序排序: [TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}, TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}, TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}, TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}]
    

    从List中查找最大/最小值的元素

    /**
         * 从List中查找最大值
         *
         * @param list      集合
         * @param keySelect 字段选择
         * @param <T>       输入类型
         * @param <U>       比较字段类型
         * @return 结果
         */
        public static <T, U extends Comparable<U>> T findMaximum(List<T> list, Function<? super T, U> keySelect) {
            notEmptyCondition(list);
            return doFindMaxOrMin(list, keySelect, true);
        }
    
        /**
         * 从List中查找最小值
         *
         * @param list      集合
         * @param keySelect 字段选择
         * @param <T>       输入类型
         * @param <U>       比较字段类型
         * @return 结果
         */
        public static <T, U extends Comparable<U>> T findMinimum(List<T> list, Function<? super T, U> keySelect) {
            notEmptyCondition(list);
            return doFindMaxOrMin(list, keySelect, false);
        }
    
    	/**
         * 根据字段查询集合最大值/最小值
         *
         * @param list      list集合
         * @param keySelect 字段选择
         * @param max       true: 最大值, false: 最小值
         * @param <T>       输入类型
         * @param <U>       比较类型
         * @return 结果
         */
        private static <T, U extends Comparable<U>> T doFindMaxOrMin
        (
                List<T> list, Function<? super T, U> keySelect, boolean max
        ) {
        	//函数返回的是Optional类, 如果没有的话就抛异常吧...e.e
            return max ? list.stream().max(Comparator.comparing(keySelect)).orElseThrow(
                    () -> new RuntimeException("抛出了不讲武德异常")
            )
                    : list.stream().min(Comparator.comparing(keySelect)).orElseThrow(
                    () -> new RuntimeException("抛出了不讲武德异常")
            );
        }
    

    测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    
            // 查找Score最大的TestUser
            TestUser maximum = FunctionalUtil.findMaximum(list, TestUser::getScore);
            System.err.println("maximum = " + maximum);
    
            // 查找Score最小的TestUser
            TestUser minimum = FunctionalUtil.findMinimum(list, TestUser::getScore);
            System.err.println("minimum = " + minimum);
        }
    

    控制台打印结果:

    maximum = TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}
    minimum = TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}
    

    合并List中某个属性值, 计算 总数/平均数

    /**
         * 将List某个字段合并, 总数/平均值
         *
         * @param list             集合
         * @param keySelect        字段选择, 不定长参数, 可以选择多个字段进行合并
         * @param mergingOperation 合并操作, 总数 / 平均数
         * @return 结果
         */
        @SafeVarargs
        public static <T> Double mergingListResult
        (
                List<T> list, MergingOperation mergingOperation,
                Function<? super T, ? extends Number>... keySelect
        ) {
            notEmptyCondition(list);
            return doMergingListResult(list, mergingOperation, keySelect);
        }
    
    /**
         * 线性表List, 根据字段计算总和/平均值
         *
         * @param list             list
         * @param keySelect        字段选择, 不定长参数, 可以选择多个字段进行合并
         * @param mergingOperation 合并操作, 总数 / 平均数
         * @return 结果
         */
        @SafeVarargs
        private static <T> Double doMergingListResult
        (
                List<T> list, MergingOperation mergingOperation,
                Function<? super T, ? extends Number>... keySelect
        ) {
        	//计算总数逻辑
            double sum = 0;
            for (Function<? super T, ? extends Number> keyFunction : keySelect) {
                sum += list.stream().mapToDouble(s -> keyFunction.apply(s).doubleValue()).sum();
            }
            switch (mergingOperation) {
            	//如果是总数合并的话就直接返回
                case SUMMING:
                    return sum;
                //要平均数的话就除以list.size()
                case AVERAGING:
                    return sum / list.size();
                default:
                    throw new RuntimeException("俺也不知道为啥会走到这个分支");
            }
        }
    

    测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    
            Double result = FunctionalUtil.mergingListResult(list, MergingOperation.SUMMING, TestUser::getScore);
            Double result2 = FunctionalUtil.mergingListResult(list, MergingOperation.SUMMING, TestUser::getScore,
                    TestUser::getWinningCount); //可选多个参数进行合并
            System.err.println("result = " + result);
            System.err.println("result2 = " + result2);
        }
    

    控制台打印结果:

    result = 510.0
    result2 = 770.0
    

    List统计数据

    /**
         * List统计数据, 包括最小值, 最大值, 平均值等等, 详情查看类{@link java.util.DoubleSummaryStatistics}
         *
         * @param list      集合
         * @param keySelect
         * @param <T>
         * @return
         */
        public static <T> DoubleSummaryStatistics getDoubleSummaryStatistics
        (
                List<T> list, Function<? super T, ? extends Number> keySelect
        ) {
            notEmptyCondition(list);
            return list.stream().collect(Collectors.summarizingDouble(s -> keySelect.apply(s).doubleValue()));
        }
    

    测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    
            DoubleSummaryStatistics result = FunctionalUtil.getDoubleSummaryStatistics(list, TestUser::getScore);
            System.err.println("result = " + result);
        }
    

    控制台打印结果:

    result = DoubleSummaryStatistics{count=4, sum=510.000000, min=110.000000, average=127.500000, max=150.000000}
    

    List转换为Map

    /**
         * 将List转换为Map, 如果有Hash冲突将会抛出异常
         *
         * @param list        list集合
         * @param keySelect   key选择
         * @param valueSelect value选择
         * @param <T>         输入类型
         * @param <K>         key类型
         * @param <V>         value类型
         * @return Map<K, V>
         */
        public static <T, K, V> Map<K, V> listToMap
        (
                List<T> list, Function<? super T, ? extends K> keySelect,
                Function<? super T, ? extends V> valueSelect
        ) {
            notEmptyCondition(list);
            return list.stream().collect(Collectors.toMap(keySelect, valueSelect));
        }
    

    测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    
            Map<String, TestUser> result = FunctionalUtil.listToMap(list, TestUser::getUsername, s -> s);
            System.err.println("result = " + result);
        }
    

    控制台输出结果:

    result = {用户2=TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}, 用户4=TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}, 用户3=TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}, 用户11111=TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}}
    

    List转其他集合, 数组转集合

    /**
         * list转其他集合
         *
         * @param list               list集合
         * @param collectionSupplier 集合实现类提供者
         * @param <T>                输入类型
         * @param <R>                返回类型
         * @return R
         */
        public static <T, R extends Collection<T>> R listToCollection(List<T> list, Supplier<R> collectionSupplier) {
            notEmptyCondition(list);
            return list.stream().collect(Collectors.toCollection(collectionSupplier));
        }
    
        /**
         * 对象数组转集合
         *
         * @param array              数组
         * @param collectionSupplier 集合实现类提供者
         * @param <T>                输入类型
         * @param <R>                返回类型
         * @return R
         */
        public static <T, R extends Collection<T>> R arrayToCollection(T[] array, Supplier<R> collectionSupplier) {
            Objects.requireNonNull(array);
            return Arrays.stream(array).collect(Collectors.toCollection(collectionSupplier));
        }
    

    测试

    这里就只演示一个, List转其他集合.

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    
    		//将List转换为LinkedList
            LinkedList<TestUser> testUsers = FunctionalUtil.listToCollection(list, LinkedList::new);
            //将List转换为ArrayDeque
            ArrayDeque<TestUser> arrayDeque = FunctionalUtil.listToCollection(list, ArrayDeque::new);
    
            System.err.println("testUsers = " + testUsers);
            System.err.println("arrayDeque = " + arrayDeque);
        }
    

    List根据某个字段去重

    /**
         * List根据某个字段去重
         *
         * @param list      list集合
         * @param keySelect 去重字段选择
         * @param <T>       输入类型
         * @param <K>       去重字段类型
         * @return 结果
         */
        public static <T, K> List<T> distinctByField(List<T> list, Function<? super T, ? extends K> keySelect) {
            notEmptyCondition(list);
            /* 这里去重的逻辑大概是这样: 将List转换为Map, Key的话为需要去重的字段, value的话为T本身
            toMap函数如果出现Hash冲突没处理的话默认是会报错的, 这里第三个参数是mergeFunction, 就是用来
            处理Hash冲突的, 这里的处理方式是这样的: 如果出现了Hash冲突就将原本的保留, 冲突的丢弃, 最终将
            map的values放入一个新的List并返回.
            */
            return new ArrayList<>(list.stream().collect(Collectors.toMap(keySelect, (T o) -> o, (p, n) -> p))
                    .values());
        }
    

    测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                // 多添加几个username为用户2的做测试
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
            }};
    
            List<TestUser> result = FunctionalUtil.distinctByField(list, TestUser::getUsername);
            System.err.println("result = " + result);
        }
    

    控制台输出的结果:

    result = [TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}, TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}]
    

    Map的排序

    1. 对Map的key进行排序

    /**
         * 排序Map, 根据key进行排序
         *
         * @param map  map集合
         * @param desc 是否降序
         * @param <K>  key类型
         * @param <T>  value类型
         * @return 用LinkedHashMap保证顺序
         */
        public static <K extends Comparable<K>, T> Map<K, T> sortMapByKey(Map<K, T> map, boolean desc) {
            notEmptyCondition(map);
            return doSortMapByKey(map, desc);
        }
    
    /**
         * 排序Map, 根据key进行排序
         *
         * @param map  map集合
         * @param desc 是否降序
         * @param <K>  key类型
         * @param <T>  value类型
         * @return 用LinkedHashMap保证顺序
         */
        private static <K extends Comparable<K>, T> Map<K, T> doSortMapByKey(Map<K, T> map, boolean desc) {
            LinkedHashMap<K, T> linkedHashMap = new LinkedHashMap<>();
            if (desc) {
                map.entrySet().stream().sorted(Map.Entry.<K, T>comparingByKey().reversed()).forEachOrdered(e -> {
                    linkedHashMap.put(e.getKey(), e.getValue());
                });
            } else {
                map.entrySet().stream().sorted(Map.Entry.<K, T>comparingByKey()).forEachOrdered(e -> {
                    linkedHashMap.put(e.getKey(), e.getValue());
                });
            }
            return linkedHashMap;
        }
    

    2. 对Map的值进行排序

    /**
         * 排序Map根据值进行排序
         *
         * @param map       map集合
         * @param keySelect 值的选择函数
         * @param desc      是否降序
         * @param <K>       key类型
         * @param <T>       元素类型
         * @return 用LinkedHashMap保证顺序
         */
        public static <K, T, U extends Comparable<U>> Map<K, T> sortMapByValue
        (
                Map<K, T> map, boolean desc, Function<? super T, ? extends U> keySelect
        ) {
            notEmptyCondition(map);
            return doSortMapByValue(map, keySelect, desc);
        }
    
    /**
         * 排序Map根据值进行排序
         *
         * @param map       map集合
         * @param keySelect 值的选择函数
         * @param desc      是否降序
         * @param <K>       key类型
         * @param <T>       元素类型
         * @return 用LinkedHashMap保证顺序
         */
        private static <K, T, U extends Comparable<U>> Map<K, T> doSortMapByValue
        (
                Map<K, T> map, Function<? super T, ? extends U> keySelect, boolean desc
        ) {
            LinkedHashMap<K, T> linkedHashMap = new LinkedHashMap<>();
            if (desc) {
                map.entrySet().stream().sorted(Map.Entry.<K, T>comparingByValue(Comparator.comparing(keySelect))
                        .reversed()).forEachOrdered(e -> {
                    linkedHashMap.put(e.getKey(), e.getValue());
                });
            } else {
                map.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.comparing(keySelect)))
                        .forEachOrdered(e -> {
                            linkedHashMap.put(e.getKey(), e.getValue());
                        });
            }
            return linkedHashMap;
        }
    

    测试

    public static void main(String[] args) {
            ArrayList<TestUser> list = new ArrayList<TestUser>() {{
                add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
                add(new TestUser("用户2", 1L, 110.0, 12, 20L));
                add(new TestUser("用户3", 2L, 130.0, 13, 200L));
                add(new TestUser("用户4", 2L, 150.0, 14, 20L));
            }};
    
            Map<Integer, List<TestUser>> result = FunctionalUtil.simpleGroupingBy(list, TestUser::getCount);
            System.err.println("未排序之前result = " + result);
    
            result = FunctionalUtil.sortMapByKey(result, true);
            System.err.println("对key降序排序result = " + result);
    
            Map<Integer, TestUser> result2 = FunctionalUtil.listToMap(list, TestUser::getCount, s -> s);
            System.err.println("未排序之前result2 = " + result2);
    
            result2 = FunctionalUtil.sortMapByValue(result2, true, TestUser::getScore);
            System.err.println("对Score降序排序之后result2 = " + result2);
        }
    

    控制台打印结果:

    未排序之前result = {11=[TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}], 12=[TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}], 13=[TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}], 14=[TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}]}
    对key降序排序result = {14=[TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}], 13=[TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}], 12=[TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}], 11=[TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}]}
    未排序之前result2 = {11=TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}, 12=TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}, 13=TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}, 14=TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}}
    对Score降序排序之后result2 = {14=TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}, 13=TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}, 11=TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}, 12=TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}}
    

    代码下载地址: https://gitee.com/nathan98/functional-util.git

    展开全文
  • 平均数的算法也比较简单,一种思路是Map端读取数据,在数据输入到Reduce之前先经过shuffle,将map函数输出的key值相同的所有的value值形成一个集合value-list,然后将输入到Reduce端,Reduce端汇总并且统计记录数...

    求平均数是MapReduce比较常见的算法,求平均数的算法也比较简单,一种思路是Map端读取数据,在数据输入到Reduce之前先经过shuffle,将map函数输出的key值相同的所有的value值形成一个集合value-list,然后将输入到Reduce端,Reduce端汇总并且统计记录数,然后作商即可。

    package mapreduce;  
    import java.io.IOException;  
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.FileSystem;
    import org.apache.hadoop.fs.Path;  
    import org.apache.hadoop.io.IntWritable;  
    import org.apache.hadoop.io.Text;  
    import org.apache.hadoop.mapreduce.Job;  
    import org.apache.hadoop.mapreduce.Mapper;  
    import org.apache.hadoop.mapreduce.Reducer;  
    import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
    import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;  
    import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
    import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;  
    public class MyAverage{  
        public static class Map extends Mapper<Object , Text , Text , IntWritable>{  
            private static Text newKey=new Text();  
            public void map(Object key,Text value,Context context) throws IOException, InterruptedException{  
                String line=value.toString();  
                System.out.println(line);  
                String arr[]=line.split("   ");  
                newKey.set(arr[0]);
                System.out.println(arr[0]);
                System.out.println(arr[1]);
                int click=Integer.parseInt(arr[1]);  
                context.write(newKey, new IntWritable(click));  
            }  
        }  
        public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable>{  
            public void reduce(Text key,Iterable<IntWritable> values,Context context) throws IOException, InterruptedException{  
                int num=0;  
                int count=0;  
                for(IntWritable val:values){  
                    num+=val.get();  
                    count++;  
                }  
                int avg=num/count;  
                context.write(key,new IntWritable(avg));  
            }  
        }  
        @SuppressWarnings("deprecation")
        public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException{  
            Configuration conf=new Configuration(); 
            conf.set("dfs.client.use.datanode.hostname", "true");
            System.out.println("start");  
            Job job =new Job(conf,"MyAverage");  
            job.setJarByClass(MyAverage.class);  
            job.setMapperClass(Map.class);  
            job.setReducerClass(Reduce.class);  
            job.setOutputKeyClass(Text.class);  
            job.setOutputValueClass(IntWritable.class);  
            job.setInputFormatClass(TextInputFormat.class);  
            job.setOutputFormatClass(TextOutputFormat.class);  
            Path in=new Path("hdfs://*:9000/user/hadoop/input/c.txt"); 
            System.out.println("in执行完毕");
            Path out=new Path("hdfs://*:9000/user/hadoop/output");
            System.out.println("out执行完毕");
            Path path = new Path("hdfs://*:9000/user/hadoop/output");// 取第1个表示输出目录参数(第0个参数是输入目录)
            FileSystem fileSystem = path.getFileSystem(conf);// 根据path找到这个文件
            if (fileSystem.exists(path)) {
                fileSystem.delete(path, true);// true的意思是,就算output有东西,也一带删除
            } 
            FileInputFormat.addInputPath(job,in);  
            FileOutputFormat.setOutputPath(job,out);  
            System.exit(job.waitForCompletion(true) ? 0 : 1);  
    
        }  
    }  

     

    转载于:https://www.cnblogs.com/miria-486/p/9982524.html

    展开全文
  • java面试宝典2012

    2012-12-16 20:43:41
    2、列出各个部门中工资高于本部门的平均工资的员工和部门号,并按部门号排序 100 3、存储过程与触发器必须讲,经常被面试到? 101 4、数据库三范式是什么? 103 5、说出一些数据库优化方面的经验? 103 6、union和...
  • JAVA面试宝典2010

    2011-12-20 16:13:24
    2、列出各个部门中工资高于本部门的平均工资的员工和部门号,并按部门号排序 91 3、存储过程与触发器必须讲,经常被面试到? 92 4、数据库三范式是什么? 94 5、说出一些数据库优化方面的经验? 95 6、union和union ...
  • 平均数的算法也比较简单,一种思路是Map端读取数据,在数据输入到Reduce之前先经过shuffle,将map函数输出的key值相同的所有的value值形成一个集合value-list,然后将输入到Reduce端,Reduce端汇总并且统计记录数...
  • java范例开发大全

    2013-03-08 20:06:54
    实例129 统计指定文件中的字符个 183 实例130 对象的序列化与反序列化 185 实例131 同时显示多个文件 187 实例132 生成zip压缩文件 189 实例133 解压缩zip文件 192 实例134 生成Excel文件 194 实例135 读取Excel...
  • Java 面试宝典

    2013-02-01 10:02:08
    Java 基础部分..................................................................................................................... 7 1、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么...
  • Java面试宝典-经典

    2015-03-28 21:44:36
    2、列出各个部门中工资高于本部门的平均工资的员工和部门号,并按部门号排序 91 3、存储过程与触发器必须讲,经常被面试到? 92 4、数据库三范式是什么? 94 5、说出一些数据库优化方面的经验? 95 6、union和union ...
  • Java面试宝典2012版

    2012-12-03 21:57:42
    2、列出各个部门中工资高于本部门的平均工资的员工和部门号,并按部门号排序 91 3、存储过程与触发器必须讲,经常被面试到? 92 4、数据库三范式是什么? 94 5、说出一些数据库优化方面的经验? 95 6、union和...
  • 最新Java面试宝典pdf版

    热门讨论 2011-08-31 11:29:22
    2、列出各个部门中工资高于本部门的平均工资的员工和部门号,并按部门号排序 91 3、存储过程与触发器必须讲,经常被面试到? 92 4、数据库三范式是什么? 94 5、说出一些数据库优化方面的经验? 95 6、union和union ...
  • Java面试宝典2012新版

    2012-06-26 19:20:00
    2、列出各个部门中工资高于本部门的平均工资的员工和部门号,并按部门号排序 91 3、存储过程与触发器必须讲,经常被面试到? 92 4、数据库三范式是什么? 94 5、说出一些数据库优化方面的经验? 95 6、union和union ...
  • Java面试笔试资料大全

    热门讨论 2011-07-22 14:33:56
    2、列出各个部门中工资高于本部门的平均工资的员工和部门号,并按部门号排序 91 3、存储过程与触发器必须讲,经常被面试到? 92 4、数据库三范式是什么? 94 5、说出一些数据库优化方面的经验? 95 6、union和union ...
  • Java面试宝典2010版

    2011-06-27 09:48:27
    2、列出各个部门中工资高于本部门的平均工资的员工和部门号,并按部门号排序 3、存储过程与触发器必须讲,经常被面试到? 4、数据库三范式是什么? 5、说出一些数据库优化方面的经验? 6、union和union all有什么...
  • java范例开发大全源代码

    热门讨论 2011-10-30 23:31:51
     实例129 统计指定文件中的字符个 183  实例130 对象的序列化与反序列化 185  实例131 同时显示多个文件 187  实例132 生成zip压缩文件 189  实例133 解压缩zip文件 192  实例134 生成Excel文件 ...
  • 接着根据分数进行排序,然后去除最高的和最低分,删除list第一条数据,以及最后一条,这样就把最高分,和最低分去除 然后统计平均分,实现思路,一样重新根据id使用groupingby重新分组 然后循环数据合并,根据i...
  • 达内 coreJava 习题答案

    2010-02-10 19:49:01
    6、输出所有的水仙花,把谓水仙花是指一个3位数,其各各位数字立方和等于其本身, 例如: 153 = 1*1*1 + 3*3*3 + 5*5*5 class DafodilNumber{ public static void main(String[] args){ System.out....
  • 2、列出各个部门中工资高于本部门的平均工资的员工和部门号,并按部门号排序 91 3、存储过程与触发器必须讲,经常被面试到? 92 4、数据库三范式是什么? 94 5、说出一些数据库优化方面的经验? 95 6、union和union ...
  • Java范例开发大全 (源程序)

    热门讨论 2011-04-27 07:47:22
     实例129 统计指定文件中的字符个 183  实例130 对象的序列化与反序列化 185  实例131 同时显示多个文件 187  实例132 生成zip压缩文件 189  实例133 解压缩zip文件 192  实例134 生成Excel文件 194 ...
  • 2、列出各个部门中工资高于本部门的平均工资的员工和部门号,并按部门号排序 91 3、存储过程与触发器必须讲,经常被面试到? 92 4、数据库三范式是什么? 94 5、说出一些数据库优化方面的经验? 95 6、union和union ...
  • java范例开发大全(pdf&源码)

    热门讨论 2013-07-04 13:04:40
    实例129 统计指定文件中的字符个 183 实例130 对象的序列化与反序列化 185 实例131 同时显示多个文件 187 实例132 生成zip压缩文件 189 实例133 解压缩zip文件 192 实例134 生成Excel文件 194 实例135 读取Excel...
  • Java范例开发大全(全书源程序)

    热门讨论 2013-04-05 11:50:26
    实例129 统计指定文件中的字符个 183 实例130 对象的序列化与反序列化 185 实例131 同时显示多个文件 187 实例132 生成zip压缩文件 189 实例133 解压缩zip文件 192 实例134 生成Excel文件 194 实例135 读取...
  • Java开发实战1200例.第2卷.part3

    热门讨论 2013-05-08 22:46:34
    实例112 计算两个日期间的月份 192 第5章 复杂查询技术 194 5.1 使用子查询 195 实例113 将子查询作为表达式 195 实例114 用子查询作为派生表 196 实例115 通过子查询关联数据 197 实例116 使用IN谓词限定查询范围...
  • Java开发实战1200例.第2卷.part2

    热门讨论 2013-05-08 22:45:35
    实例112 计算两个日期间的月份 192 第5章 复杂查询技术 194 5.1 使用子查询 195 实例113 将子查询作为表达式 195 实例114 用子查询作为派生表 196 实例115 通过子查询关联数据 197 实例116 使用IN谓词限定查询范围...
  • Java开发实战1200例.第2卷.part1

    热门讨论 2013-05-08 22:44:13
    实例112 计算两个日期间的月份 192 第5章 复杂查询技术 194 5.1 使用子查询 195 实例113 将子查询作为表达式 195 实例114 用子查询作为派生表 196 实例115 通过子查询关联数据 197 实例116 使用IN谓词限定查询范围...
  • Java基础部分......................................................................................................2 1、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?.....2 2、...
  • 实例057 用List集合传递学生信息 70 实例058 用TreeSet生成不重复自动排序 随机数组 71 实例059 Map映射集合实现省市级联选择框 73 第4章 字符串处理技术 75 4.1 格式化字符串 76 实例060 把数字格式化为货币字符串 ...

空空如也

空空如也

1 2 3
收藏数 47
精华内容 18
关键字:

java统计list平均数

java 订阅