如何在Java中实现复杂字符串的集合(列表,映射?)?

时间:2010-04-23 13:46:41

标签: java sorting collections

问题 - 我有类似以下条目的内容,其中1000条:

args1=msg args2=flow args3=content args4=depth args6=within ==> args5=content
args1=msg args2=flow args3=content args4=depth args6=within args7=distance ==> args5=content
args1=msg args2=flow args3=content args6=within ==> args5=content
args1=msg args2=flow args3=content args6=within args7=distance ==> args5=content
args1=msg args2=flow args3=flow ==> args4=flowbits
args1=msg args2=flow args3=flow args5=content ==> args4=flowbits
args1=msg args2=flow args3=flow args6=depth ==> args4=flowbits
args1=msg args2=flow args3=flow args6=depth ==> args5=content
args1=msg args2=flow args4=depth ==> args3=content
args1=msg args2=flow args4=depth args5=content ==> args3=content
args1=msg args2=flow args4=depth args5=content args6=within ==> args3=content
args1=msg args2=flow args4=depth args5=content args6=within args7=distance ==> args3=content

我正在做某种建议方法。比方说, args1 = msg args2 = flow args3 = flow ==> args4 = flowbits

如果句子包含msg,flow和另一个流程,那么我应该返回flowbits的建议。

我该怎么做呢?我知道我应该扫描(每当在textarea上按下一个字符时)匹配的列表或数组并返回结果,但是,1000个条目,我应该如何实现它?

我正在考虑使用HashMap,但我可以这样做吗?

< “味精,流,流”, “flowbits” >

另外,在一个句子中,参数可能不是有序的,所以假设它是flow,flow,msg然后我无法匹配HashMap中的任何内容,因为键是“msg,flow,flow”。

在这种情况下我该怎么办?请帮忙。万分感谢!

6 个答案:

答案 0 :(得分:4)

Map的密钥可以是另一个MapSet。看起来您需要的只是Map<Set<String>, String>Map<Map<String, String>, Map.Entry<String, String>> - 不确定这些“args1”,“args2”的相关位置。

答案 1 :(得分:1)

换句话说,尽量不要在解析器中完成所有逻辑。拆分逻辑,使解析器只是检测结构,然后构建对象以帮助您实施规则。解析器可以轻松检测参数并使用它们来创建列表。

如果你创建一个类来包含你的参数,那么:

public class Arg {
    public int number;
    public String value;

    public Arg(int num, String val) {
        this.number = num;
        this.value = val;
    }

    @Override
    public String toString()
    {
   return "[Arg num=" + number + ", value=" + value + "]";
    }

}

然后你可以将它们放在一个简单的Hashtable中。

Map<Arg> argList = new HashMap<Arg>();

然后你可以使用计数器和contains()或indexOf()等来做逻辑。

使用Arg类也可以轻松排序。如果需要按参数位置排序的列表,则为其创建一个Comparator。

import java.util.Comparator;

public class ArgNumComparator implements Comparator<Arg> {
    public int compare(Arg o1, Arg o2) {
       if (o1.number == o2.number) {
        return 0;
       }
       return o1.number < o2.number ? -1 : 1 ;
   }    
}

通过参数值进行排序更加容易,因为您可以重用strings的comparativeTo()。

import java.util.Comparator;

public class ArgValComparator implements Comparator<Arg>
{
    public int compare(Arg o1, Arg o2)
   {
       return o1.value.compareTo(o2.value);
   }
}

然后,要进行排序,请使用Collections.sort(),如下所示:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ArgList{
    public static void main(String[] args)  {
        //args1=msg args2=flow args3=content args4=depth args6=within ==> args5=content
        List<Arg> l = new ArrayList<Arg>();  
        // hard-coded example instead of more likely parsing
        l.add(new Arg(1, "msg"));
        l.add(new Arg(2, "flow"));
        l.add(new Arg(3, "content"));
        l.add(new Arg(4, "depth"));
        l.add(new Arg(5, "flow"));
        l.add(new Arg(6, "within"));

    Collections.sort(l, new ArgValComparator()); // take your pick of comparators

    System.out.println(l); // uses the toString() of Arg.
    }
}

编辑:向Arg添加了一个toString()方法,并将示例中的列表更改为具有两个“流”参数。

使用新的toString代码运行会将以下内容添加到控制台:

  

[[Arg num = 3,value = content],[Arg   num = 4,value = depth],[Arg num = 2,   value = flow],[Arg num = 5,value = flow],   [Arg num = 1,value = msg],[Arg num = 6,   值=内]]

正如您所看到的,两个具有value =“flow”的参数现在彼此相邻。要检测多个args,其中value =“flow”可以这样做:

boolean flowFound = false;
for (Arg arg : l){
   if (arg.value.compareToIgnoreCase("flow") == 0) {
      if (flowFound)  //already found one? {
         // action when second "flow" exists
         System.out.println("2nd flow found");
      }
      else {
         flowFound = true;  // found the first "flow"
      }
   }          
}

答案 2 :(得分:0)

是的,你可以做&lt;“msg,flow,flow”,“flowbits”&gt;在hashmap中。这是最好的解决方案,我不知道。

答案 3 :(得分:0)

乍一看,这看起来很适合解析器和正式语法而不是集合。 ANTLR是一种流行的Java解析器生成器。

如果参数可以按任何顺序出现,解析器将不会解决您的问题。在那种情况下,我会使用某种组合规则和操作的Case对象,并使用简单的Map<String,List<Case>>来查找可能适用于给定文本的实例(您将从中提取单个单词)用于探测地图的文本,可以组合每个探测返回的列表。

我没有时间提供完整的示例,但Case对象可能看起来像这样:

public interface Case {
    boolean evaluate(String text);
    String result();
}

答案 4 :(得分:0)

您可以为每一行创建一个对象并封装其中的逻辑。如果输入与描述完全相同,您应该能够使用简单的正则表达式提取args并捕获组,然后为每个arg调用对象上的setter。然后,您的数据结构将只是这些对象的列表。

答案 5 :(得分:0)

由于字符串出现的顺序并不重要,因此您可以在创建密钥时按字母顺序排列它们。假设你想要相同的建议,msg,flow,flow和flow,msg,flow和flow,flow,msg - alphabetized,它们是“flow,flow,msg”,这就是你用作密钥的方法。 / p>