Skip to main content
 首页 » 编程设计

java-me中j2me中按两个或多个条件过滤结果

2025年01月19日8Terrylee

我正在尝试使用 RecordFilter 过滤一些记录界面。在我的应用程序中,我有几个与此类似的界面,用户可以在其中输入 ID 或名称(他/她可以同时输入或都不输入)

enter image description here

这是我到目前为止所做的事情:

客户过滤器。

这里,如果用户没有输入 ID,我会传递 0 作为默认值,这就是我评估 customerID!=0 的原因

public class CustomerFilter implements RecordFilter { 
 
    private String mName_Filter; 
    private int mID_Filter; 
 
    public CustomerFilter(String name_Filter, int id_Filter) { 
        this.mName_Filter = name_Filter.toLowerCase(); 
        this.mID_Filter = id_Filter; 
    } 
 
    public boolean matches(byte[] candidate) { 
        try { 
            ByteArrayInputStream bis = new ByteArrayInputStream(candidate); 
            DataInputStream dis = new DataInputStream(bis); 
            int customerID = dis.readInt(); 
            String customerName = dis.readUTF().toLowerCase(); 
            if ((customerName != null && customerName.indexOf(mName_Filter) != -1) && (customerID != 0 && customerID == mID_Filter))                 
                return true; 
            if (customerName != null && customerName.indexOf(mName_Filter) != -1 && customerID == 0)  
                return true; 
            if (customerName == null && (customerID != 0 && customerID == mID_Filter))  
                return true; 
            if (customerName == null && customerID == 0)  
                return true; 
 
        } catch (IOException ex) { 
            //What's the point in catching a exception here??? 
        } 
        return false; 
    } 
} 

搜索方法:

注意:此方法位于我称为“RMSCustomer”的类中,我在其中处理与 RMS 访问相关的所有内容。 search 方法接收两个参数(id 和 name)并使用它们来实例化过滤器。

  public Customer[] search(int id, String name) throws RecordStoreException, IOException { 
        RecordStore rs = null; 
        RecordEnumeration recEnum = null; 
        Customer[] customerList = null; 
        try { 
            rs = RecordStore.openRecordStore(mRecordStoreName, true);            
            if (rs.getNumRecords() > 0) { 
                CustomerFilter filter = new CustomerFilter(name, id);             
                try { 
                    recEnum = rs.enumerateRecords(filter, null, false); 
                    if (recEnum.numRecords() > 0) {                   
                        customerList = new Customer[recEnum.numRecords()]; 
                        int counter = 0; 
                        while (recEnum.hasNextElement()) { 
                            Customer cust; 
                            int idRecord = recEnum.nextRecordId(); 
                            byte[] filterRecord = rs.getRecord(idRecord);                       
                            cust = parseRecord(filterRecord); 
                            cust.idRecord = idRecord; 
                            customerList[counter] = cust; 
                            counter++; 
                        } 
                    }  
                    else{ 
                        customerList = new Customer[0]; 
                        //How to send a message to the midlet from here 
                        //saying something like "No Record Exists.Please select another filter" 
                    }                    
                } finally { 
                    recEnum.destroy(); 
                } 
            } 
            else{ 
                //How to send a message to the midlet from here 
                //saying something like "No Record Exists.Please Add record" 
            } 
        } finally { 
            rs.closeRecordStore(); 
        } 
        return customerList; 
    } 

尽管如此,上面显示的代码可以工作,但我仍然有一些疑问/问题:

过滤器中:

1) 如何改进评估过滤器可能值(名称、id)的代码?如果我有更多过滤器怎么办?我必须测试所有可能的组合吗?

2)如果用户既没有输入ID也没有输入姓名,我应该显示所有记录还是应该显示一条消息“请输入姓名或ID”?在这种情况下你会怎么做?

3)当我不能在过滤器中做任何事情时,为什么我必须在过滤器中放置一个try-catch?我无法从那里显示任何警报,或者可以吗?

搜索方法中:

1)如何通过该方法向用户显示正确的消息?类似于“无记录”(请参阅​​我的代码中的“ELSE”部分

抱歉,如果我问了太多问题,那只是因为有过滤器的完整示例。

提前致谢

请您参考如下方法:

How can I improve the code that evaluates the possible values of the filters (name,id)?

ID 是记录中的第一个字段,也是搜索速度最快的字段。如果 ID 匹配,那么客户名称是什么并不重要。通常,您将查找 ID 匹配或客户名称匹配的记录,因此一旦 ID 匹配,您就可以返回 true。这是我对 CustomerFilter 的建议类:

public class CustomerFilter implements RecordFilter { 
 
    private String mName_Filter; 
 
    //Use Integer instead of int.  
    //This way we can use null instead of zero if the user didn't type an ID. 
    //This allows us to store IDs with values like 0, -1, etc. 
    //It is a bit less memory efficient, 
    //but you are not creating hundreds of filters, are you? (If you are, don't). 
    private Integer mID_Filter;  
 
    public CustomerFilter(String name_Filter, Integer id_Filter) { 
        this.mName_Filter = normalizeString(mName_Filter); 
        this.mID_Filter = id_Filter; 
    } 
 
    //You should move this function to an StringUtils class and make it public. 
    //Other filters might need it in the future. 
    private static String normalizeString(final String s){ 
        if(s != null){       
            //Warning: you might want to replace accentuated chars as well. 
            return s.toLowerCase(); 
        } 
        return null; 
    } 
 
    public boolean matches(byte[] candidate) { 
        ByteArrayInputStream bis = new ByteArrayInputStream(candidate); 
        DataInputStream dis = new DataInputStream(bis);  
 
        try {                
            if(mID_Filter != null){ 
                //If the ID is unique, and the search is ID OR other fields, this is fine 
                int customerID = dis.readInt(); 
 
                if(mID_Filter.intValue == customerID){ 
                    return true; 
                } else { 
                    return false;  
                } 
            } 
 
            if(mName_Filter != null){ 
                String customerName = normalizeString(dis.readUTF()); 
                if(customerName != null && customerName.indexOf(mName_Filter) != -1){ 
                    return true; 
                } 
            } 
 
            if(mID_Filter == null && mName_Filter == null){ 
                return true; // No filtering, every record matches. 
            } 
        } catch (IOException ex) { 
            //Never swallow exceptions. 
            //Even if you are using an underlying ByteArrayInputStream, an exception  
            //can still be thrown when reading from DataInputStream if you try to read 
            //fields that do not exists. 
 
            //But even if no exceptions were ever thrown, never swallow exceptions :) 
            System.err.println(ex); 
 
            //Optional: throw ex; 
        } finally { 
            //Always close streams. 
            if(bis != null){ 
                try { 
                    bis.close(); 
                } catch(IOException ioe){ 
                    System.err.println(ioe); 
                } 
            } 
 
            if(dis != null){ 
                try { 
                    dis.close(); 
                } catch(IOException ioe){ 
                    System.err.println(ioe); 
                } 
            } 
        } 
 
        return false; 
    } 
} 




What if I had more filters?? Will I have to test all the possible combinations??

这取决于您的项目。通常 ID 是唯一的,不存在具有相同 ID 的两条记录。在这种情况下,您应该明确设计屏幕,以便用户了解他要么键入 ID,要么填写其他字段。条件是这样的:

idMatches OR (field1Matches AND field2Matches AND ... fieldNMatches) 

如果用户未输入任何内容,则将返回所有记录。

但话又说回来,这更多的是一个用户体验问题,我不知道它是否适合您的要求。

从编程的角度来看,很明显,添加的字段越多,过滤器就会变得越困惑。为了防止这种情况,您可以使用类似 Decorator 的模式, Composite ,甚至 Chain of responsibility 。不过,您可能必须用良好的设计来换取性能。




If the user doesn’t enter neither a ID nor a name, should I display all the records or should I display a message "Please enter a name or ID"?? What would you do in this case?

这要看情况。还有其他方法可以查看所有记录吗?如果是这样,则显示该消息。




Why do I have to put a try-catch in the filter when I can't do anything there?? I can't show any alert from there or can I?

你不应该。该类只负责过滤,不负责与用户交互。您仍然可以记录 catch 子句中的错误,然后再次引发异常。这会将异常传播到 RMSCustomer.search ,因此无论客户端代码调用该函数,都将以与处理该方法引发的其他异常相同的方式处理异常。但保留finally 子句来关闭流。




How can I show a proper message to the user from that method? something like "No records" (see the "ELSE" parts in my code)

您不应该在 RMSCustomer 类中执行任何与 GUI 相关的操作(例如显示对话框)。即使您没有使用模型- View - Controller 模式,您仍然希望让您的类专注于单一职责(管理记录)。这称为Single responsibility principle 。 将您的类与 GUI 隔离将使您能够在没有 GUI 的环境中测试并重用它。 当结果为零时,无记录情况应由屏幕处理。 lenght == 0 的数组在这里就可以了,屏幕会显示“No results”消息。对于其他类型的错误,您可以扩展 Exception 类并抛出您自己的自定义异常,即:RecordParsingException ,来自RMSCustomer.search方法。然后,屏幕类会将不同的异常映射到用户语言的错误消息。