Java 这两种方法的区别在于

Java 这两种方法的区别在于,java,Java,我必须使用一个方法调用一个joiner作为连接字符串a和b的参数,我必须检查两边是否都是empy。 这两种代码都有效,但我不明白为什么我的评论者要我用他的方式来做。如果有人能向我解释它的好处,那就太好了 我的方法 public static String join(String a, String b) { StringJoiner sj = new StringJoiner(" "); if (a.endsWith("dieci") || a.endsWith("veinti"

我必须使用一个方法调用一个joiner作为连接字符串a和b的参数,我必须检查两边是否都是empy。 这两种代码都有效,但我不明白为什么我的评论者要我用他的方式来做。如果有人能向我解释它的好处,那就太好了

我的方法

public static String join(String a, String b) {
    StringJoiner sj = new StringJoiner(" ");
    if (a.endsWith("dieci") || a.endsWith("veinti")) {
        return a + b;
    }       
    if (a.equals("")) {
        return b;
    }
    if (b.contentEquals("")) {
        return a;
    }
    sj.add(a);
    sj.add(b);
    return sj.toString();
}
他的方法

public static String join(String a, String b) {
    if (a.endsWith("dieci") || a.endsWith("veinti")) {
        return a + b;
    }
    return Stream.of(a, b).filter(s ->!s.isEmpty()).collect(Collectors.joining(" "));       
}

他的方法简单得多;有一句话基本上是这样说的:

取字符串a和b,去掉空字符串,用空格连接其余的字符串,返回结果

这使我们非常清楚地看到该准则的意图。它还可以防止出现错误,因为在分散的代码中出现打字错误或逻辑错误会更容易,从而将实现分解为多个不同的情况

诚然,这可能比您的代码更难理解,因为初学者可能不理解流。但是,一旦您理解了它们,至少在这种情况下阅读肯定会更容易,但并非总是如此,而且它使编写此类方法变得更容易。因此,现在学习并使用这些Java结构比以后更好

他的代码也更加灵活。如果必须使该方法连接三个字符串,那么对其方法的唯一修改就是将Stream.ofa,b更改为Stream.ofa,b,c。您的方法将需要更多的更改

此外,使用isEmpty比.equals更清楚,因为它用更自然的英语表达了你在做什么。这又一次防止了打字错误,就像你不小心做的那样。等于一个空格或什么的


还有,为什么要使用两种不同的方法equals和contentEquals来做相同的事情?这令人困惑。他的方法不能做到这一点。

首先,在这类事情中总有一些观点。也许还有沟通和个性。这真的值得你去争论吗?如果您的审阅者希望在审阅中重写您的代码,那么有什么害处1

现在谈谈实质问题

从表面上看,一旦您熟悉Java8流,您的审阅者的代码显然更简洁、更容易理解。我想,假设在这个项目中工作的每个人都应该熟悉,如果不是流利的话。它可以更清楚地处理边缘情况

我还认为,使用StringJoiner连接两个字符串并在它们之间留一个空格是过分的。一个简单的连接表达式比您现在所做的更有效,也更容易理解

   return a + " " + b;
唯一的另一个不同点是性能:

我不清楚哪一个会表现更好。您需要对这两个版本进行基准测试才能确定。 如果您正在优化使用的CPU周期或生成的垃圾,则两个版本都不是最优的。 但请注意,只有在有具体证据表明此方法的性能对整个应用程序至关重要时,才应该针对性能进行优化。如果不是这样的话,那么优化很可能是浪费您的时间,几分钟/小时的时间可能比浪费数百万个CPU周期的成本更高

仅供参考,如果我需要优化性能,我会编写如下方法:

public static String join(String a, String b) {
    if (a.isEmpty()) {
        return b;
    } else if (b.isEmpty()) {
        return a;
    } else if (a.endsWith("dieci") || a.endsWith("veinti")) {
        return a + b;
    } else {
        return a + " " + b;
    }
}
我将留给读者去弄清楚我做了什么,以及为什么。我所做的那些可能是毫无根据的假设

1-危害在于,如果他正在破坏你或他的工作效率


2-Java8已经有4年多的历史了。专业人士有足够的时间学习使用其新功能。如果你刚从大学毕业,而大学没有教你Java8流。。。尽快学习

也许是因为它比较短,一旦你了解了流是如何工作的,就更容易理解了?@meriton shorter代码并不总是意味着更好的代码。我们可以使用a++b.trim来完成与流基本相同的操作,这也比流解决方案短,尽管它会在这个过程中生成额外的字符串操作,因此运行时效率较低,即使Java会通过垃圾收集来处理运行时效率是另一个主题。创建流、过滤器、收集器和底层缓冲区可能要繁重得多。然而,今天的方法减少了代码重复。可能初始代码更快。如果我来进行代码审查,我会将steam语句重构为一个单独的方法,比如使用可变参数joinNonBlank。并检查是否有空白。然而,在这里,您使用特殊规则组合一些数字,这可能需要另一个命名方法来测试合并案例。这只是一个错误,它会自动完成,我很累。谢谢你的重播。@nanoroccia抓住你了,这就是我要说的重点。代码越长,发生这种简单错误的可能性就越大。但正如罗曼所说,代码越短并不总是越好,因为它通常可读性越差。然而,在这种情况下,较短的代码增加了我的op的可读性
伊尼翁。@mapeters我的评论不是关于一般的可读性,而是关于效率。通常情况下,人们必须做出权衡。您是否更关心可能需要更多CPU时间的内存效率,或者内存不是一个限制因素,您可以只关注执行性能?通常,需要分析不同的算法,以查看运行时和内存行为的差异。本示例中的trim解决方案是否优于stream解决方案(stream解决方案也会在堆上创建额外的对象),需要进行测量以给出定性的结果feedback@RomanVottner这是有道理的。我想说的是,通常对于这样的简单场景,内存和性能不是很关键,因为与代码的其他区域的内存/性能相比,它们可能可以忽略不计,因此可读性更为重要。当然,这完全取决于用例。@mapters如果您为嵌入式系统或特别是移动设备设计应用程序,这些考虑应该是您思维的一部分,如果不是一般工作流程的一部分。CPU密集度更高的算法会消耗更多的电源/电池,而这类设备上的内存通常非常有限,尽管现代移动设备的可用内存比电脑在上千年左右要多得多——这就是我在uni上只学习基本java的情况。我也认为使用joiner有点过分,但他坚持这样做,所以一方面他要求干净的代码轻视它,同时也要求像joiner那样只连接一个空格。谢谢你的回复也可能是你误解了他。他可能是在另一个背景下建议使用StringJoiner;e、 g.当您有一个要加入的字符串列表时。但事实仍然是,您现在需要学习Java8流。你可能还需要更努力地向你的评论者学习。。。这意味着要理解他对你说的话。”因为在我看来,他基本上是在告诉你正确的事情。提示:不要认为你比他更了解Java编码,因为证据表明你不。。。然而在这一点上,他是你的老师。