您的位置:首页 > 编程语言 > Java开发

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

2016-07-30 17:13 585 查看
        先说说场景,最近接第三方的足球走地数据,需要将这些数据入库,设计到一个足球的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相对于其他的版本来说有什么新的特性功能,试着去使用它们,给自己带来方便,会有意想不到的效果。 

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jdk 性能测试