巧妙利用JDK1.8新特性解决多if判断及其性能测试

本文介绍了一种高效处理第三方足球赛事数据的方法,通过使用枚举类型结合Java 8的新特性,实现了灵活的数据映射,避免了冗长的if或switch-case语句,提高了代码的可读性和维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        先说说场景,最近接第三方的足球走地数据,需要将这些数据入库,设计到一个足球的eventType的整理,我们自己的库中有一套我们自己的eventType,这些eventType包括进球,红黄牌等事件。第三方数据可能将两个队的进球事件分开成HomeGoal和AwayGoal事件,而在我们的库中将这两个事件合并成一个事件Goal。

       将第三方的事件对应到我们自己库中的事件,在解决方式上你可能想到的第一个方法是使用if或者switch case,或者某种设计模式。我想说这些方式都不可取,先说if和switch case,eventType种类太多,当前有20多种,还不能保证以后只减不增,用if或者switch case,你确定你要写20++种if或case判断吗?再说使用设计模式,使用策略模式?不管使用何种设计模式,面对20++种eventType,需要20++个类,还要随着以后eventType的动态增加来随时增加类,随时维护代码。违背原则。

        那是不是就要问了,那有什么好的解决方案呢?我建议的解决方案是使用enum+jdk1.8新特性。前提是你的项目使用了jdk1.8哦。

        enum类可以这样定义:

<span style="font-size:18px;">import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.zhangyu.databus.core.enums.MatchEventType;
import com.zhangyu.databus.fetch.enums.BetgeniusSports;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by zhudan on 2016/7/26.
 */
public enum BetgeniusEventType {
    ALL(-1, "全部",MatchEventType.ALL),
    AWAY_GOAL(0, "AwayGoal",MatchEventType.SCORE),
    AWAY_PENALTY(1, "AwayPenalty",MatchEventType.PENALTY),
    AWAY_DANGEROUS_FREEKICK(2, "AwayDangerousFreeKick",MatchEventType.DANGEROUS_FREE_KICK),
    AWAY_CORNER(3, "AwayCorner",MatchEventType.CORNER),
    AWAY_ATTACKING_FREEKICK(4, "AwayAttackingFreeKick",MatchEventType.DANGEROUS_FREE_KICK),
    AWAY_DANGEROUS_ATTACK(5, "AwayDangerousAttack",MatchEventType.DANGEROUS_ATTACK),
    AWAY_CORNER_DANGER(6, "AwayCornerDanger",MatchEventType.DANGEROUS_CORNER),
    AWAY_ATTACK(7, "AwayAttack",MatchEventType.ATTACK),
    AWAY_FREEKICK(8, "AwayFreeKick",MatchEventType.FREE_KICK),
    AWAY_SAFE(9, "AwaySafe",MatchEventType.BALL_SAFE),
    SAFE(10, "Safe",MatchEventType.BALL_SAFE),
    HOME_SAFE(11, "HomeSafe",MatchEventType.BALL_SAFE),
    HOME_FREEKICK(12, "HomeFreeKick",MatchEventType.FREE_KICK),
    HOME_ATTACK(13, "HomeAttack",MatchEventType.ATTACK),
    HOME_CORNER_DANGER(14, "HomeCornerDanger",MatchEventType.DANGEROUS_CORNER),
    HOME_DANGEROUS_ATTACK(15, "HomeDangerousAttack",MatchEventType.DANGEROUS_ATTACK),
    HOME_ATTACKING_FREEKICK(16, "HomeAttackingFreeKick",MatchEventType.DANGEROUS_FREE_KICK),
    HOME_CORNER(17, "HomeCorner",MatchEventType.CORNER),
    HOME_DANGEROUS_FREEKICK(18, "HomeDangerousFreeKick",MatchEventType.DANGEROUS_FREE_KICK),
    HOME_PENALTY(19, "HomePenalty",MatchEventType.PENALTY),
    HOME_GOAL(20, "HomeGoal",MatchEventType.SCORE),
    YELLOWCARDDANGER(21, "YellowCardDanger",MatchEventType.POSSIBLE_YELLOW_CARD),
    //TODO
    AWAY_SAFE_FREEKICK(22, "AwaySafeFreeKick",MatchEventType.FREE_KICK),
    HOME_SAFE_FREEKICK(23, "HomeSafeFreeKick",MatchEventType.FREE_KICK);
    
    private static Logger logger = LoggerFactory.getLogger(BetgeniusSports.class);

    private static final Object _LOCK = new Object();

    private static Map<Integer, BetgeniusEventType> _MAP;
    private static Map<String, BetgeniusEventType> _NAME_MAP;
    private static Map<String, BetgeniusEventType> _STATE_MAP;
    private static List<BetgeniusEventType> _LIST;
    private static List<BetgeniusEventType> _ALL_LIST;

    static {
        synchronized (_LOCK) {
            Map<Integer, BetgeniusEventType> map = new HashMap<>();
            Map<String, BetgeniusEventType> nameMap = new HashMap<>();
            Map<String,BetgeniusEventType> stateMap=new HashMap<>();
            List<BetgeniusEventType> list = new ArrayList<>();
            List<BetgeniusEventType> listAll = new ArrayList<>();
            for (BetgeniusEventType item : BetgeniusEventType.values()) {
                map.put(item.getValue(), item);
                nameMap.put(item.getName(), item);
                listAll.add(item);
                if (!item.equals(ALL)) {
                    list.add(item);
                }
            }

            _MAP = ImmutableMap.copyOf(map);
            _NAME_MAP = ImmutableMap.copyOf(nameMap);
            _STATE_MAP=ImmutableMap.copyOf(stateMap);
            _LIST = ImmutableList.copyOf(list);
            _ALL_LIST = ImmutableList.copyOf(listAll);
        }
    }

    private int value;
    private String name;
    private MatchEventType matchEventType;

    BetgeniusEventType(int value, String name, MatchEventType matchEventType) {
        this.value = value;
        this.name = name;
        this.matchEventType=matchEventType;
    }

    public String getName() {
        return name;
    }

    public int getValue() {
        return value;
    }

    public MatchEventType getMatchEventType(){
        return matchEventType;
    }

    public static BetgeniusEventType get(int value) {
        try {
            return _MAP.get(value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    public static BetgeniusEventType getByName(String name) {
        try {
            return _NAME_MAP.get(name);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    public static List<BetgeniusEventType> list() {
        return _LIST;
    }

    public static List<BetgeniusEventType> listAll() {
        return _ALL_LIST;
    }

    public static Map<String, BetgeniusEventType> getBetgeniusStateMap(){
       return _STATE_MAP;
    }
}</span>
        拿AWAY_GOAL(0,"AwayGoal",MatchEventType.SCORE)进行说明,0不用说,仅仅是个序号,"AwayGoal"是第三方数据的eventType,MatchEventType.SCORE是我们自己的一套eventType,enum类中的listAll和list方法,分别返回不同结构的list,其中我使用到了listAll方法,接着往下看。

    使用jdk1.8新特性中的stream().filter()结合lamda表达式,可以这样处理。直接返回MatchEventType中的name属性,即返回我们自己的这一套eventType。

<span style="font-size:18px;">BetgeniusEventType.listAll().stream().
                            filter((s) -> s.getName().equals("AwayGoal")).
                            findFirst().get().getMatchEventType().getName()</span>
   那这同普通的在for循环下取值然后进行if判断有什么优势呢?

   我做了一个简单的性能测试:

<span style="font-size:18px;">public static void main(String[] args) {
        long foreachstart = System.currentTimeMillis();
        for (BetgeniusEventType type:BetgeniusEventType.listAll()
             ) {
            if(type.getName().equals("AwaySafe")){
                System.out.println(type.getName());
            }
        }
        long foreachend = System.currentTimeMillis();
        System.out.println(foreachstart-foreachend);

        long filterstart=System.currentTimeMillis();
        System.out.println(BetgeniusEventType.listAll().stream().
                filter((s) -> s.getName().equals("AwaySafe")).
                findFirst().get().getName());
        long filterend=System.currentTimeMillis();
        System.out.println(filterstart-filterend);
    }</span>
测试结果如下:
    
    咱既然选择了使用jdk1.8,那么也要明白jdk1.8相对于其他的版本来说有什么新的特性功能,试着去使用它们,给自己带来方便,会有意想不到的效果。 
  

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值