如果这是一个愚蠢的问题,我很抱歉,但我是Java链表和数组列表的新手。
我想做的是:我有一个文本文件,我逐字逐句地浏览。我想创建一个链表的数组列表,其中文本中的每个单词后面都是链表中的单词。
想想这段文字:猫走向那棵红色的树。
我希望链接列表的数组列表是这样的:
猫红
|
猫行
|
至
|
红树
我现在拥有的是:
while(dataFile.hasNext()){
secondWord = dataFile.next();
nWords++;
if(nWords % 1000 ==0) System.out.println(nWords+" words");
//and put words into list if not already there
//check if this word is already in the list
if(follows.contains(firstWord)){
//add the next word to it's linked list
((LinkedList)(firstWord)).add(secondWord);
}
else{
//create new linked list for this word and then add next word
follows.add(new LinkedList<E>().add(firstWord));
((LinkedList)(firstWord)).add(secondWord);
}
//go on to next word
firstWord = secondWord;
}
它给了我很多错误。我该怎么做才能做到最好?(使用链表,我知道哈希表和二进制树更好,但我需要使用链表)
ArrayList
不是外部列表的最佳数据结构,至少部分困难源于对列表列表的错误使用。
在您的实现中,假定follows
是LinkedLists的ArrayList,声明如下:
ArrayList<LinkedList<String>> follows = new ArrayList<>();
follows.contains(firstWord)
的结果永远不会为true,因为follows
包含类型为LinkedList的元素,而不是String。firstWord
是一个String,因此不会是follows
的元素,而是作为follows
的元素的ArrayList的第一个元素。
下面提供的解决方案对外部列表follows
使用Map
,或者更具体地使用HashMap
。Map是优选的,因为当搜索第一个单词时,使用Map的平均查找时间将为O(1),而列表的平均查找速度为O(n)。
String firstWord = dataFile.next().toLowerCase();
Map<String, List<String>> follows = new HashMap<>();
int nWords = 0;
while (dataFile.hasNext())
{
String secondWord = dataFile.next().toLowerCase();
nWords++;
if (nWords % 1000 == 0)
{
System.out.println(nWords + " words");
}
//and put words into list if not already there
//check if this word is already in the list
if (follows.containsKey(firstWord))
{
//add the next word to it's linked list
List list = follows.get(firstWord);
if (!list.contains(secondWord))
{
list.add(secondWord);
}
}
else
{
//create new linked list for this word and then add next word
List list = new LinkedList<String>();
list.add(secondWord);
follows.put(firstWord, list);
}
//go on to next word
firstWord = secondWord;
}
地图将如下所示:
the: [cat, red]
cat: [walks]
to: [the]
red: [tree]
walks: [to]
我还对您的实现进行了以下更改:
不要在下列单词列表中添加重复单词。请注意,
Set
将是更适合此任务的数据结构,但您明确指出了使用LinkedList
的要求。使用
String.toLowerCase()
将所有字符串移到小写,以便"the"one_answers"the"得到同等处理。(请确保您也将此应用于firstWord
的初始值,它不会出现在您提供的代码中。)
请注意,此解决方案和您最初的尝试都假定标点符号已被删除。
您不应该使用直接类实现,而应该使用它们的接口来简化开发(以及其他原因)。因此,请改为每隔一段时间进行类型转换,将变量声明为List
,并在初始化时定义类。由于您还没有发布相关的代码来重新定义它,我可以给您举一个例子:
List<List<String>> listOfListOfString = new LinkedList<>(); //assuming Java 7 or later used
List<String> listOne = new ArrayList<>();
listOne.add("hello");
listOne.add("world");
listOfListOfString.add(listOne);
List<String> listTwo = new ArrayList<>();
listTwo.add("bye);
listTwo.add("world");
listOfListOfString.add(listTwo);
for (List<String> list : listOfListOfString) {
System.out.println(list);
}
这将打印:
[hello, world]
[bye, world]
请注意,现在您可以将listOne
或listTwo
中任何一个的实现更改为LinkedList
:
List<String> listOne = new LinkedList<>();
//...
List<String> listTwo = new LinkedList<>();
代码的行为也将相同。无需进行任何类型转换即可使其工作。
相关:
- 这对";程序到接口"