有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java:使用大量半恒定标志检查优化循环中的循环?

我有这样一个简单的嵌套结构。(这是真实问题的简化版本。其中一些实际使用哈希_集。)

class A{  AF a_field; B[] bs;}
class B{  BF b_field; C[] cs;}
class C{  CF c_field; D[] ds;}
class D{  DF d_field; }
static A[] as;  // loosely speaking, it has about 4000 D

psuedo代码方法“f”看似复杂,但其实很容易理解:-

int f(int TYPE){ //TYPE is 0 - 40 
    int retur=0;
    for(int n=0;n<as.length;n++){
    .   if(some cheap condition of TYPE){ //use only "TYPE" , cheap (1)
    .   .   as[n].a_field.doExpensiveAA(); //expensive OPERATION, use only "a_field" (Ex retur+=a_field) 
    .   }else if(some cheap condition of TYPE){ //use only "TYPE" (2)
    .   .   as[n].a_field.doExpensiveAB(); //expensive OPERATION, use only "a_field" (Ex retur-=a_field)
    .   } // .... and a lot of them
    .   for(int m=0;m<bs.length;m++){
    .   .   if(some cheap condition of TYPE){ //use only "TYPE" (3)
    .   .   .   as[n].bs[m].b_field.doExpensiveBA(); (*)//use only "b_field" 
    .   .   }else if(some cheap condition of TYPE){//use only "TYPE" (4)
    .   .   .   as[n].bs[m].b_field.doExpensiveBB(); (/) //use only "b_field"
    .   .   } // .... and a lot of them
    .   .   for( ..cs .. ){...for(...ds...) {...}...} 
    .   }
    }
}

(为了缩进,我拼命地加上。)

在每个时间步中都调用“f”:-

public static void caller (){
    for(int n=0;n<40;n++){ f(n); }
}

请注意,TYPE是条件检查中唯一使用的变量,对于单个“f”调用,它是常量

虽然每个条件检查都非常便宜,但当它位于最内部的循环中时,它会花费大量的CPU周期。如何优化“调用者”和/或“f”

我的想法是

  1. 为每个“类型”打开“f”,但会有很多脏代码难以维护。。。像这样

    公共静态无效调用方(){ f1();f2();f3()。。。f40(); }

  2. 使用开关盒!它比if-else快,但将情况0切换到40很难看。这种情况不能再像“检查奇数/偶数类型”那样分组了,因此代码的可维护性较低

编辑1(回答Partha Sarathi Ghosh):检查位只是示例,所以位的索引并不重要,甚至可以是“>;8”,只是要注意,所有条件都取决于类型

编辑2:+-*/只是一个例子,它是一个使用a_字段、b_字段等的任意函数(实际情况是在Opengl中设置3D纹理或系统变量)。。。反恐精英。。。和ds。。。是类似但不同的昂贵操作

编辑3:添加“A[]as”包含约4000个D的信息

编辑4(回答Partha Sarathi Ghosh):从int编辑xxx_字段的类型,以显示它们是不同的类


共 (1) 个答案

  1. # 1 楼答案

    需要将函数作为参数传递给递归函数。在我为你们准备基本算法时,请看post

    您还需要使用自定义标记接口以相同的递归方法传递这些不同类型的数据

    这是您的示例程序

    import java.util.List;
    import java.util.ArrayList;
    
    
    
    /** The Invoker class */
    class Switch {
        List<Command> commandList = new ArrayList<Command>();
        Switch() {
            commandList.add(new IncreementCommand()); //Level 1 Operation
            commandList.add(new MultipleCommand());
            commandList.add(new DecrementCommand());
            //If level 4 need same operation like level 1
            commandList.add(new IncreementCommand()); 
    
        }
    
        public int execute(CustomMarker a, int lvl){
            int rtr = 0;
            Command cmd = commandList.get(lvl-1); //Level 1 means 1st operation
            return execute(a, lvl, rtr, cmd);
        }
    
    
        /** The Command interface */
        interface Command {
            int execute(int data, int rtr);
        }
    
       private int execute(CustomMarker a, int lvl, int rtr, Command cmd){
           if(lvl == 0){
               return cmd.execute(a.getData(), rtr);
           }
           else {
               lvl ;
               if(a.getSubData() != null && a.getSubData().length>0){
                   for (int i = 0; i < a.getSubData().length; i++) {
                     rtr = execute(a.getSubData()[i], lvl, rtr, cmd);
                   }
               }
               return rtr;
           }
       }
    
       //Inner classes
       class IncreementCommand implements Command {
           @Override    // Command
           public int execute(int data, int rtr) {
              return rtr+data;
           }
        }
    
        /** The Command for turning off the light - ConcreteCommand #2 */
        class MultipleCommand implements Command {
            @Override    // Command
            public int execute(int data, int rtr) {
               return rtr*data;
            }
        }
    
        /** The Command for turning off the light - ConcreteCommand #2 */
        class DecrementCommand implements Command {
            @Override    // Command
            public int execute(int data, int rtr) {
               return rtr-data;
            }
        }
    }
    
    /** The Custom Marker interface */
    interface CustomMarker {
        //It will return your int a_field or b_field
       public int getData();
       public CustomMarker[] getSubData();
    }
    
    
    //Level 1
    class A implements CustomMarker {  int a_field; B[] bs;
        public int getData() {
            return a_field;
        }
        public CustomMarker[] getSubData() {
            return bs;
        }
    }
    //Level 2
    class B implements CustomMarker {  int b_field; C[] cs;
        public int getData() {
            return b_field;
        }
        public CustomMarker[] getSubData() {
            return cs;
        }
    }
    //Level 3
    class C implements CustomMarker {  int c_field; D[] ds;
        public int getData() {
            return c_field;
        }
        public CustomMarker[] getSubData() {
            return ds;
        }
    }
    //Level 4
    class D implements CustomMarker {  int d_field; 
        public int getData() {
            return d_field;
        }
        public CustomMarker[] getSubData() {
            return null;
        }
    }
    
    
    /* The test class or client */
    public class TestClass {
       static A[] as;
       public static void main(String[] args){
    
    
    
          CustomMarker topLevel = new CustomMarker() {
            @Override
            public int getData() {
                // TODO Auto-generated method stub
                return 0;
            }
            @Override
            public CustomMarker[] getSubData() {
                return as;
            }
          };
    
          Switch mySwitch = new Switch();
          for(int n=1;n<=3;n++){ 
              mySwitch.execute(topLevel, n); 
          }
       }
    }
    

    在这个程序中,我对a_fieldb_field使用了与int相同的数据类型。 但你可以用Object试试。因此,在每个操作中执行块类型转换。你不需要在typecast之前检查你的程序是否能正确处理级别和类型

    我将新操作减少到了41次。40操作和+1开关(操作控制器)

    编辑:更新了Switch类的execute public方法,存在复制粘贴错误