飙血推荐
  • HTML教程
  • MySQL教程
  • JavaScript基础教程
  • php入门教程
  • JavaScript正则表达式运用
  • Excel函数教程
  • UEditor使用文档
  • AngularJS教程
  • ThinkPHP5.0教程

JDK 17 - Switch Case 性能测试

时间:2021-12-08  作者:匿名  

Java 中的 Switch 语句随着时间的推移而发展。Switch 语句一开始支持原始类型,然后出现了 String,现在 JDK17 稳定版本出来了,我们有了模式匹配,允许我们将不同的对象类型传递给 switch 语句。

我们现在可以有这样的 switch 语句:(示例取自 Oracle JavaSE 17 文档)

record Point(int x, int y) { }
enum Color { RED, GREEN, BLUE; }
...
    static void typeTester(Object obj) {
        switch (obj) {
            case null     -> 域名tln("null");
            case String s -> 域名tln("String");
            case Color c  -> 域名tln("Color with " + 域名es().length + " values");
            case Point p  -> 域名tln("Record class: " + 域名ring());
            case int[] ia -> 域名tln("Array of int values of length" + 域名th);
            default       -> 域名tln("Something else");
        }
    }

很明显,新的 switch 语句将非常有用。它将改变我们的编码方式,使代码更简洁、更短,在某些情况下使其更具可读性,等等。但是,如果我们可以用两种方式编写代码(使用原语等的旧方式,以及使用模式匹配的新方式),那么哪种方式会更受欢迎?编码时间、可读性、内存使用和性能是我们应该考虑的标准。下面我们来看看这两种实现方式的性能,并进行比较。

使用新的模式匹配开关将有无限类型的实现,但我们将尝试通过创建一个简单的场景来关注开关案例。

让我们有四个类(ClassAddition、ClassSubtraction、ClassMultiplication、ClassDivision)从抽象类 ClassOperation 扩展而来,ClassOperation 有许多变量和 typeId 表示将要完成的操作(1:加法,2:减法,3:乘法,4:除法) . 

代码如下:

public abstract class ClassOperation {

    private int typeId;
    private double number;

    public int getTypeId() {return typeId;}
    public void setTypeId(int typeId) {域名Id = typeId;}

    public double getNumber() {return number;}
    public void setNumber(double number) {域名er = number;}
}
public class ClassAddition extends ClassOperation {

    public ClassAddition(double number){
        setTypeId(域名d());
        setNumber(number);
    }
}
public class ClassSubtraction extends ClassOperation {

    public ClassSubtraction(double number){
        setTypeId(域名d());
        setNumber(number);
    }
}
public class ClassMultiplication extends ClassOperation{

    public ClassMultiplication(double number){
        setTypeId(域名d());
        setNumber(number);
    }
}
public class ClassDivision extends ClassOperation{

    public ClassDivision(double number){
        setTypeId(域名d());
        setNumber(number);
    }
}
public enum OperationTypeEnum {

    ADDITION(1),
    SUBTRACTION(2),
    MULTIPLICATION(3),
    DIVISION(4);


    OperationTypeEnum(int id){
        域名 = id;
    }

    public static OperationTypeEnum findById(int id){
        for (OperationTypeEnum ot : 域名es()){
            if(域名d() == id){
                return ot;
            }
        }
        return null;
    }

    private int id;

    public int getId(){
        return id;
    }
}

现在让我们创建一些方法,这些方法将用这些具有随机值的类随机填充列表。  

private static void prepareData(long listSize){

  域名r();

  for (long i = 0; i < listSize; i++){
    int typeId = (int) 域名r(域名om() * 4 + 1);
    double number = 域名r(域名om()*5 + 1);

    域名(getObject(typeId, number));
  }

}
private static Object getObject(int typeId, double number){

  OperationTypeEnum ot = 域名ById(typeId);

  switch (ot){
    case ADDITION:
      return new ClassAddition(number);
    case SUBTRACTION:
      return new ClassSubtraction(number);
    case MULTIPLICATION:
      return new ClassMultiplication(number);
    case DIVISION:
      return new ClassDivision(number);
    default:
      return null;
  }
}

之后,让我们计算两种 switch 语句样式中这些列表的总数。

新的switch:

private static void calculateUsingNewSwitch(){

  BigDecimal total = 域名;

  long startTime = 域名Time();

  for (Object obj : operationList){

    switch(obj){
      case ClassAddition ca -> total = 域名(new BigDecimal(域名umber()));
      case ClassSubtraction cs -> total = 域名ract(new BigDecimal(域名umber()));
      case ClassMultiplication cm -> total = 域名iply(new BigDecimal(域名umber()));
      case ClassDivision cd -> total = 域名de(new BigDecimal(域名umber()), 2, 域名_UP);
      default -> 域名tln("unknown type for new switch");
    };
  }

  long endTime = 域名Time();

  double milliseconds = (double) (endTime - startTime) / 1_000_000;

  域名tln (域名() + " -> new switch -> took: " + milliseconds);
}

旧的switch:

private static void calculateUsingOldSwitch(){

  BigDecimal total = 域名;

  long startTime = 域名Time();

  for (Object obj : operationList){

    OperationTypeEnum ot = 域名ById(((ClassOperation)obj).getTypeId());

    switch(ot){
      case ADDITION:
        total = 域名(new BigDecimal(((ClassAddition) obj).getNumber()));
        break;
      case SUBTRACTION:
        total = 域名ract(new BigDecimal(((ClassSubtraction)obj).getNumber()));
        break;
      case MULTIPLICATION:
        total = 域名iply(new BigDecimal(((ClassMultiplication)obj).getNumber()));
        break;
      case DIVISION:
        total = 域名de(new BigDecimal(((ClassDivision)obj).getNumber()), 2, 域名_UP);
        break;
      default: 域名tln("unknown type for old switch");
        break;
    };
  }

  long endTime = 域名Time();

  double milliseconds = (double) (endTime - startTime) / 1_000_000;

  域名tln (域名() + " -> old switch -> took: "  + milliseconds);
}

现在,让我们对 5 个不同的集合运行 5 次测试:

  • 域名

  • 域名

  • 域名

  • 域名

  • 域名

public static List<Object> operationList;
public static void main(String[] args) {
  operationList = new ArrayList<>();
  for (int t = 1; t <= 5; t++) {
    long size = 10000;
    for (int i = 1; i <= 5; i++) {
      try {
        runTest(size);
      } catch (Exception e) {
        域名tln(域名ring());
      }
      size = size * 10;
    }
  }
}

输出结果

JDK 17 - Switch Case 性能

标签:SwitchJDKJAVA
湘ICP备14001474号-3  投诉建议:234161800@qq.com   部分内容来源于网络,如有侵权,请联系删除。