20015jjw
V2EX  ›  问与答

请问这种逻辑特别简单,但是写起来非常蛋疼的 Java 怎么办?

  •  
  •   20015jjw · Dec 5, 2017 · 2962 views
    This topic created in 3108 days ago, the information mentioned may be changed or developed.

    我知道各位会说换其他 Java 替代语言(Kotlin...),但是公司代码库暂时不支持。

    现在我有一堆User, 然后有个 Helper 会逐个检查这些 User,然后如果 User 的 Email 地址或者电话号码对应输入,就 return 那个 User。代码如下(手工重写的,省去了很多细节)

    public User getUserFromEmail(String email) {
      for (User user : getUsers()) {
        if (email.equals(user.getEmail())) {
          return user;
        }
      } 
    }
    
    public User getUserFromPhoneNumber(String phoneNumber) {
      for (User user : getUsers()) {
        if (phoneNumber.equals(user.getPhoneNumber())) {
          return user;
        }
      } 
    }
    

    那这俩方程基本就差一点点,所以我想把他们合并起来。我现在的想法写出来感觉非常恶心。

    public User getUserFromEmail(String email) {
      User(email, null);
    }
    
    public User getUserFromPhoneNumber(String phoneNumber) {
      getUser(null, phoneNumber);
    }
    
    private User getUser(String email, String phoneNumber) {
      String query, userInfo;
      if (email != null) {
        query = email;
      } else if (phoneNumber != null) {
        query = phoneNumber;
      } else {
        return null;
      }
      for (user : getUsers()) {
        if (email != null) {
          userInfo = user.getEmail();
        } else if (phoneNumber != null) {
          userInfo = user.getPhoneNumber();
        }
        if (query.equals(userInfo)) {
          return user;
        }
      }
    }
    

    蛋疼的地方有 2 个,一个是合并后结果比原来长很多,还有一个是这样每个循环都要做多一个 check,显得非常愚蠢,不知道各位 Java 大佬有没有什么办法可以帮到我,先谢谢了 ><

    Supplement 1  ·  Dec 5, 2017
    忘说了,但是 Lambda 也不支持... Java 8 整个就不支持,因为项目需要支持旧版安卓...
    19 replies    2017-12-06 00:52:38 +08:00
    hyyou2010
        1
    hyyou2010  
       Dec 5, 2017
    定义这么个东西:
    public class UserCompareItems{
    public String name;//为 null 时表示不必对这一项
    public String phone;//非 null 时表示比对这一项
    public String otherItems;
    }

    然后在 User 类中实现一个和 UserCompareItems 比较的接口
    以后只传这个类的对象来挑选 user

    ----------临时想的,没验证,不一定好,仅供参考
    cloud107202
        2
    cloud107202  
       Dec 5, 2017
    这个算是 OO 语言给思维带来的枷锁。试图从 List 中 filter 一些结果,但是要根据不同的动态条件。纯 OO 语言里不太好做,或者需要动用设计模式。FP 里就是把怎样取属性并比较这个动作(function/ first-class function ) 当成变量传进去而已。

    举个例子,边界判断要自己补充下
    https://gist.github.com/liyuntao/54bc04e963fa969b2d82903d51bfea69
    SuperMild
        3
    SuperMild  
       Dec 5, 2017 via iPhone
    电话号码不可能含 @ ,判断一下字符就可以自动选择不同的流程了
    SuperMild
        4
    SuperMild  
       Dec 5, 2017 via iPhone
    增加一个叫 getFromEmailOrPhonenumber 的 wraper
    20015jjw
        5
    20015jjw  
    OP
       Dec 5, 2017
    @cloud107202
    你的想法我挺喜欢,但是 Java 还不支持,所以很痛苦... 我大概实现了一个类似的,但是无奈效果还是感觉不如原来的,因为还是比原来的长,而且比原来的难读很多。谢谢了。
    @hyyou2010 welp,简直蛋疼... 如果就 email 和电话感觉远不要这么麻烦。
    marknote
        6
    marknote  
       Dec 5, 2017 via iPhone
    用 lambda 吧
    20015jjw
        7
    20015jjw  
    OP
       Dec 5, 2017
    @SuperMild 我也想到了,但感觉虽然这里可以用,但是换一种情况就又蛋疼了... 而且还是少不了每次循环的电话 /邮箱 check...

    ```
    for (...) {
    if (query.is_number && query.equals(User.getPhoneNumber()) {
    return user;
    } else if (query.is_email && query.equals(User.getEmail()) {
    return user;
    }
    }
    ```
    canbingzt
        8
    canbingzt  
       Dec 5, 2017
    直接 query.equals(user.getEmail()) || query.equals(user.getPhoneNumber()) 就可以了吧
    邮箱和电话号码应该不会相同吧
    zjp
        9
    zjp  
       Dec 5, 2017 via Android
    如果还有更多属性需要查找,#2 的行为模版化的方法就能体现出优势来 只是没有 lambda 写起来更长了…
    cloud107202
        10
    cloud107202  
       Dec 5, 2017
    @20015jjw 给你的代码就是 java8 的 lambda API...
    SoloCompany
        11
    SoloCompany  
       Dec 5, 2017 via iPhone
    实在用不了 j8 还可以用 org.apache.common-collections 顶一下,别想可以有多大改进,只是换一种抽象( functor 或说算子)而已
    kran
        12
    kran  
       Dec 5, 2017 via iPhone
    用反射,传字段名和值
    kx5d62Jn1J9MjoXP
        13
    kx5d62Jn1J9MjoXP  
       Dec 5, 2017
    自定义一个 Interface
    interface Matcher {
    boolean matches(User user);
    }

    通用方法
    User getUser(Matcher matcher) {
    for (User user : getUsers()) {
    if (matcher.matches(user) return user;
    }
    return null;
    }

    这是很基本的东西, 上面有人说用 lamda 也好用 stream api 的 filter 也好都是同一个道理
    这种东西在 Java 里面到处都有
    LxExExl
        14
    LxExExl  
       Dec 5, 2017 via iPhone
    没写过 java
    PHP 的话有 schema 直接 queryFrom 然后 whereEquals...

    帮顶了
    evitceted
        15
    evitceted  
       Dec 5, 2017
    rxjava
    20015jjw
        16
    20015jjw  
    OP
       Dec 5, 2017 via Android
    @cloud107202 我的意思是 java 8 不能用 很难受...
    @ssynhtn 对这个也很难读 我想到了但是写出来不可能比那俩原方程短了
    @SoloCompany 一会看看 谢谢 但是我觉得可能 @canbingzt 的办法暂时就够了 没想到这个 hhhh 谢谢啦
    yrom
        17
    yrom  
       Dec 5, 2017
    android studio 3.0 已经支持 java 8 部分特性了(尤其是 lambda )
    YellowLittleDog
        18
    YellowLittleDog  
       Dec 5, 2017 via Android
    rxjava 链起来
    20015jjw
        19
    20015jjw  
    OP
       Dec 6, 2017 via Android
    @yrom 我们的 codebase 不支持...
    @YellowLittleDog ...那也太麻烦了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1180 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 61ms · UTC 17:52 · PVG 01:52 · LAX 10:52 · JFK 13:52
    ♥ Do have faith in what you're doing.