【问题标题】:Java 8 ArrayList equalityJava 8 ArrayList 相等
【发布时间】:2017-06-26 11:56:58
【问题描述】:

我正在尝试使用两个不同的人阅读过的两个书籍列表并进行比较。如果第一个列表中的一本书(这是一个由字符串标题和字符串作者组成的构造函数)等于另一个列表中的一本书,那么我将它添加到 commonBooks 列表中。这是我到目前为止得到的,但我不断收到这个建议:“添加返回语句”或“更改为 void”

这是我目前所拥有的:

public static ArrayList<Book> commonBooks(Person a, Person b) {

    ArrayList<Book> personA = a.getRead();
    ArrayList<Book> personB = b.getRead();
    ArrayList<Book> sameBooks = new ArrayList<Book>();

    if (personA.size() < personB.size()) {
        for (int i = 0; i < personA.size(); i++) {
            Book ndx = personA.get(i);
            if (personB.contains(ndx)) {
                sameBooks.add(ndx);
            } else if (personB.size() < personA.size()) {
                for (int i1 = 0; i1 < personB.size(); i1++) {
                    Book ndx1 = personB.get(i1);
                    if (personB.contains(ndx1)) {
                        sameBooks.add(ndx1);
                    } else if (personB.size() < personA.size()) {
                        for (int i2 = 0; i1 < personB.size(); i2++) {
                            Book ndx2 = personB.get(i2);
                            if (personB.contains(ndx2)) {
                                sameBooks.add(ndx2);
                            }

                        }
                    } else {
                        return sameBooks;
                    }

                }
            }
        }
    } else {
        return sameBooks;
    }

}

【问题讨论】:

  • 程序中的每个条件都需要返回一个值。否则,您最终需要在条件块之外返回一个。这只是确保无论满足条件如何都始终返回值的一种方式。这适用于期望返回值的方法。或者按照编译器的建议删除所有返回语句并将方法标记为 void :)

标签: java arraylist


【解决方案1】:

这是一个 java 8 流式解决方案:

import java.util.List;
import java.util.stream.Collectors;

class Class {
  public static List<Book> commonBooks(Person a, Person b) {
    List<Book> personA = a.getRead();
    List<Book> personB = b.getRead();
    return personA.stream()
      .filter(personB::contains)
      .collect(Collectors.toList());
  }
}

【讨论】:

  • 已经可以假设 OP 有一个有效的 equals (否则, contains() 将失败)。
  • 太好了,我会从答案中删除它。
【解决方案2】:

如果您的方法声明返回ArrayList,则通过您的代码的所有可能路径都必须返回ArrayList。 VHS 的answer 正确指出了一个解决方法:只在一个地方退出,返回一个ArrayList,并且所有路径都必须通过。

另一个超出您最初问题的解决方法是使用更简单的代码:

HashSet<Book> readByA = new HashSet<>(a.getRead());
readByA.retainAll(b.getRead()); // remove all books that b has not read
return new ArrayList<>(readByA);

不过,使用 HashSets 需要您在 Book 类中实现 equals()hashCode() 方法。许多 IDE 将提供为您实现它们。另一方面,对于大量书籍,这将比您当前的代码快得多。


原始代码也至少有一个主要错误,因为如果personA.size() &gt;= personB.size() 它返回一个空列表。因此,例如,给定两个相同的列表,它目前不会返回任何书籍,因为它们是共同的!

再次重写,这次没有集合:

ArrayList<Book> readByB = b.getRead();
ArrayList<Book> sameBooks = new ArrayList<Book>();
for (Book b : a.getRead()) {
    if (readByB.contains(b)) sameBooks.add(b);
}
return sameBooks;

请注意,在所有条件相同的情况下,较短的代码比较长的代码片段更易于阅读和理解。这是选择的原因之一......

for (Book b : a.getRead()) {

...到...

ArrayList<Book> readByA = a.getRead();
// ...
for (int i = 0; i < readByA.size(); i++) {
   Book b = readByA.get(i);

...您节省了 2 行代码(66%!),并且不再被两个不再需要的辅助变量 ireadByA 混淆。

【讨论】:

  • 谢谢,但这对我的项目来说有点太高级了。
  • 我添加了更多代码,这次没有使用集合。请注意,即使有 VHS 的修复,您当前的代码也过于复杂,并且会为许多输入产生错误的结果。
【解决方案3】:

你想多了!

假设您有一个集合 [a, b, c] 和另一个集合 [b, c, d]

您只需要遍历一个集合并将其与另一个集合进行比较。例如:

is 'a' in [b, c, d] ? no don't add a
is 'b' in [b, c, d] ? yes add b
is 'c' in [b, c, d] ? yes add c
Result: [b, c]

注意到您不需要循环第二组了吗?您从未评估过d,但您已经知道它不在第一个列表中。您已经检查了第一个列表中的每个项目,因此 'd' 无法匹配 [a, b, c]

for (int i = 0; i < personA.size(); i++) {
    Book ndx = personA.get(i);
    if (personB.contains(ndx)) {
        sameBooks.add(ndx);
    }
}
return sameBooks;

【讨论】:

    【解决方案4】:

    Java Compare Two Lists

    您可以尝试CollectionUtils 中的intersection()subtract() 方法。

    intersection() 方法为您提供了一个包含常见元素的集合,而subtract() 方法为您提供了所有不常见的元素。

    他们也应该注意相似的元素

    我相信你的 Book 类应该实现Comparator 接口,这样你才能正确使用它。

    【讨论】:

    • 使用集合和retainAll 更简单——不需要外部依赖。您也没有回答 OP 的原始问题“我的代码有什么问题”
    【解决方案5】:

    这是我到目前为止得到的,但我不断收到这个建议:“添加 return 声明”或“更改为 void”

    并非您方法中的所有逻辑流都在您的方法签名中返回指定的返回类型 (ArrayList&lt;Book&gt;)。在您的if 语句中,您需要更正一些流程才能返回。

    public static ArrayList<Book> commonBooks(Person a, Person b) {
    
    ArrayList<Book> personA = a.getRead();
    ArrayList<Book> personB = b.getRead();
    ArrayList<Book> sameBooks = new ArrayList<Book>();
    
    if (personA.size() < personB.size()) {
        for (int i = 0; i < personA.size(); i++) {
            Book ndx = personA.get(i);
            if (personB.contains(ndx)) {
                sameBooks.add(ndx);
            } else if (personB.size() < personA.size()) {
                for (int i1 = 0; i1 < personB.size(); i1++) {
                    Book ndx1 = personB.get(i1);
                    if (personB.contains(ndx1)) {
                        sameBooks.add(ndx1);
                    } else if (personB.size() < personA.size()) {
                        for (int i2 = 0; i1 < personB.size(); i2++) {
                            Book ndx2 = personB.get(i2);
                            if (personB.contains(ndx2)) {
                                sameBooks.add(ndx2);
                            }
    
                        }
                    } else {
                        //return sameBooks;
                        break;
                    }
    
                }
            }
        }
    } 
    
    return sameBooks;
    
    
    }
    

    【讨论】:

    • 请注意,虽然这修复了警告,但代码仍然被破坏:如果 personA.size() >= personB.size(),它返回一个空的书籍列表...
    • 谢谢,感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    • 2020-10-27
    • 1970-01-01
    • 2018-07-09
    • 1970-01-01
    相关资源
    最近更新 更多