我有两个非常大的名单要比较。我使用retainAll()方法对它们进行了比较,得到了常用元素的列表。但我也想得到类似的比赛。
ArrayList<String> list1 = new ArrayList<String>(Arrays.asList("John","Mary"," Mr. John Marsh","Mrs. Mary Dsouza","abc","xyz"));
ArrayList<String> list2 = new ArrayList<String>(Arrays.asList("John","Mary","Tim","Sam"));
list1.retainAll( list2 );
System.out.println( list1 );
这给了我输出[约翰,玛丽]
我想要类似的比赛,如[John,Mary,John Marsh先生,Mary Dsouza夫人]
如何进行?只是一个想法就足够了。
答案 0 :(得分:3)
好的,虽然我害怕发布这个答案,因为我觉得它很粗糙,但我仍然会继续发布。手指交叉:)。
retainAll
在内部使用equals
,因为string
是final
class
,我们无法操纵它,但我们可以围绕它创建wrapper
并提供自定义equals
实施。但这增加了空间复杂性。
这就是我所做的(在equals方法中使用contains
)。
public class FindAlike{
public static void main(String[] args) {
ArrayList<StringWrapper> list1 = new ArrayList<StringWrapper>(Arrays.asList(new StringWrapper("John"),new StringWrapper("Mary")
,new StringWrapper(" Mr. John Marsh"),new StringWrapper("Mrs. Mary Dsouza"),new StringWrapper("abc"),new StringWrapper("xyz")));
ArrayList<StringWrapper> list2 = new ArrayList<StringWrapper>(Arrays.asList(new StringWrapper("John"),new StringWrapper("Mary"),
new StringWrapper("Tim"),new StringWrapper("Sam")));
list1.retainAll( list2 );
System.out.println( list1 );
}
private static class StringWrapper{
private String value;
public StringWrapper(String value) {
this.value = value;
}
public String getValue(){
return this.value;
}
@Override
public boolean equals(Object obj) {
return this.value.contains(((StringWrapper)obj).getValue());
}
@Override
public String toString() {
return this.value;
}
}
}
对于给定的数据,我得到以下输出 - [John,Mary,John Marsh先生,Mary Dsouza夫人]
答案 1 :(得分:0)
试试这个
for(String s1 : list1)
{
for (String s2: list2)
{
if(s1.equals(s2) || s1.contains(s2) || s2.contains(s1))
{
list3.add(s1);
}
}
}
list3为您提供所需的元素。
答案 2 :(得分:0)
我猜你不想对这些字符串进行任何语义分析。如果它只是一个字符串比较,请检查此post并分析这些相似性算法。
我强调下面的那些算法(如果该帖子已经死了)
我不认为你可以减少迭代次数,因为它总是(应该)是list1.length * list2.lenght。您可以优化的唯一区域是检查相似性的位置。另外我想指出正则表达式和包含操作是昂贵的。所以看看你是否可以在那个地方使用上述算法之一。
如果您想出更好的解决方案,请及时通知我们。干杯!!