我正在用Java编写一个android应用程序,我需要显示ListView
。
但是在创建ListView
之前,我需要用数据填充Adapter
。
我有一个ArrayList
的字符串,我想通过ArrayList
搜索该EditText
。
我的Arraylist
有10万多个条目。
ArrayList
获得ABC。ArrayList
中获取ABC,AAC,ACC,ADC等信息,因此在这种情况下_需要替换一个字符。它也应该适用于彼此相邻而不是彼此相邻的多个下划线。ArrayList
获取ABC,AAC,ACC,ADC,ABAC,ABBC ...,因此在这种情况下,%需要替换多个字符。它也应该适用于多个%而不是彼此相邻。我认为这与Windows中的星号*相同。希望您能提供帮助。
答案 0 :(得分:2)
严重的未回答:请考虑不要在您的应用中执行此操作。
当您处理如此大量的数据时,您确实不希望这种处理发生在(可能很便宜的)手机硬件上。迟早,有些人会在硬件不足的情况下使用您的应用程序,然后他们会抱怨“该应用程序非常慢”。
含义:考虑在某种后端服务中执行此操作。然后,使用内置的技术来处理大量文本数据,例如solr。因此,是的,应用程序可能会在您键入内容时向您的服务发送字符串,并且服务会发回建议,列表等。
答案 1 :(得分:1)
您可以尝试以下方法。首先,我们将创建一个与您的搜索词匹配的正则表达式,然后按照Korashen的建议,使用paralellStream()
过滤列表。
正则表达式(?<=[_%])|(?=[_%])
将在_
和%
处拆分字符串,同时保留定界符。例如,如果拆分"A_B"
,结果将是["A","_","B"]
,而不是["A","B"]
。
private static List<String> filterByTerm(List<String> list, String term) {
StringBuilder regexBuilder = new StringBuilder();
String[] array = term.split("(?<=[_%])|(?=[_%])");
for(String s : array) {
switch(s) {
case "_":
regexBuilder.append(".");
break;
case "%":
regexBuilder.append(".*");
break;
default:
regexBuilder.append(Pattern.quote(s));
}
}
String regex = regexBuilder.toString();
return list.parallelStream().filter(s -> s.matches(regex)).collect(Collectors.toList());
}
已验证的最低示例:
List<String> input = new ArrayList<>();
input.add("ABC");
input.add("AAC");
input.add("ACC");
input.add("ADC");
String term = "AB_";
filterByTerm(input, term).forEach(System.out::println);
给出ABC
的输出。
答案 2 :(得分:1)
ArrayList
字符串不是此任务的正确数据结构。搜索此类列表的唯一方法是遍历所有列表,这将很慢。您需要一个数据结构来支持您正在执行的查询。这样做的代价可能是增加了内存占用。
字符的树形结构似乎可以正常工作。您将用下面的树表示单词AAB,ABA和ABB:
A
/ \
A B
/ / \
B A B
我也非常同意GhostCat,您可能不想这样做。
下面是一个快速实现。我不能保证它会完美或最佳地工作-这是对可能的证明,而不是可用于生产的代码。我尚未使用大型数据集对其进行过测试。
它仅支持下划线规则,但对其进行修改应足够简单,以支持多字符匹配。
一个通用接口,由根节点和实际char节点共同实现,并包含默认搜索实现:
interface CharTree
{
List<CharNode> getChildren();
default Optional<CharNode> getChild(char character)
{
return getChildren().stream()
.filter(ch -> ch.getCharacter() == character)
.findFirst();
}
default void search(final String pattern, final StringBuilder builder, final Set<String> results)
{
if (pattern.isEmpty())
{
results.add(builder.toString());
return;
}
char character = pattern.toCharArray()[0];
final List<CharNode> candidates;
if (character == '_')
{
candidates = getChildren();
}
else
{
candidates = getChild(character)
.map(Collections::singletonList)
.orElse(Collections.emptyList());
}
for (final CharNode node : candidates)
{
builder.append(node.getCharacter());
node.search(pattern.substring(1, pattern.length()), builder, results);
builder.deleteCharAt(builder.length() - 1);
}
}
}
基本的根实现,带有静态方法来构建树:
class Root implements CharTree
{
private Root() { }
@Getter private List<CharNode> children = new ArrayList<>();
public static Root buildTree(final List<String> words)
{
final Root root = new Root();
for (final String word : words)
{
CharTree current = root;
for (char character : word.toCharArray())
{
Optional<CharNode> node = current.getChild(character);
if (node.isPresent())
{
current = node.get();
}
else
{
final CharNode tmp = new CharNode(character);
current.getChildren().add(tmp);
current = tmp;
}
}
}
return root;
}
}
简单字符节点(注释来自龙目岛)
@Data
@ToString(of = "character")
class CharNode implements CharTree
{
private final char character;
private List<CharNode> children = new ArrayList<>();
}
一些单元测试,以防有人担心:
@Test
public void one()
{
final List<String> words = Arrays.asList("aaa", "bbb", "ccc");
final CharTree root = Root.buildTree(words);
final Set<String> results = new HashSet<>();
root.search("aaa", new StringBuilder(), results);
Assert.assertEquals(1, results.size());
Assert.assertTrue(results.contains("aaa"));
}
@Test
public void two()
{
final List<String> words = Arrays.asList("aaa", "aba", "abb");
final CharTree root = Root.buildTree(words);
final Set<String> results = new HashSet<>();
root.search("a_a", new StringBuilder(), results);
Assert.assertEquals(2, results.size());
Assert.assertTrue(results.contains("aaa"));
Assert.assertTrue(results.contains("aba"));
}
@Test
public void three()
{
final List<String> words = Arrays.asList("aaa", "aba", "abb");
final CharTree root = Root.buildTree(words);
final Set<String> results = new HashSet<>();
root.search("___", new StringBuilder(), results);
Assert.assertEquals(3, results.size());
Assert.assertTrue(results.contains("aaa"));
Assert.assertTrue(results.contains("aba"));
Assert.assertTrue(results.contains("abb"));
}