大家好,
在开发我的项目时,我实现了这样的场景。我有一个LinkedList,其中包含100
学生类对象。
我的方案是,
我需要从LinkedList
rollNo = 98 中获取一个特定的学生类对象。所以我使用了下面的代码。
我的pojo课程是,
public class Student {
private int rollNo ;
private String name;
// getters & setters
}
我的主要课程是,
public class MainClass {
List<Student> list = null;
public MainClass(){
list = new LinkedList<Student>();
}
public static void main(String... args){
MainClass mainClass = new MainClass();
mainClass.addStudentDetail();
Student obj = mainClass.getStudentObject(98);
// other Stuff with obj
}
private void addStudentDetail() {
for(int i=1; i<=100; i++){
Student obj = new Student();
obj.setRollNo(i);
obj.setName("Name"+i);
list.add(obj);
}
}
private Student getStudentObject(int rollNo) {
int listLength = list.size();
for(int i=0; i<listLength; i++){
if(list.get(i).getRollNo() == rollNo)
return list.get(i);
}
return null;
}
}
要获取Student对象,其中rollNo = 98,
这需要98 iterations
。
那么如果我的列表大小 1,00,000 会发生什么?我需要{strong> rollNo = 99,999 的Student
对象?
是否有其他简单方法可以使用where condition
获取一个特定对象?
注意:
很抱歉,我不需要将HashMap
与 rollNo 一起使用作为密钥。我的需要是只使用LinkedList
。这是我的要求。
希望我能在这里得到一个好的解决方案。
答案 0 :(得分:4)
使用Map
rollNo
作为键,Student
实例作为值。这是&#34; index&#34;的常用方法。这样的集合使查找尽可能高效
更新:
如果您想快速搜索,则需要某种索引。查看Java的HashMap源代码,看看如何存储密钥,这可能会让您对案例有所了解
答案 1 :(得分:1)
如果您使用LinkedList,那么它需要98次迭代才能找到学生。您可以使用地图,并按键找到学生。键可以是rollNo,也可以是学生自己的值。
答案 2 :(得分:1)
在java中,主要使用两种类型的列表,它们是 ArrayList 和 LinkedList 。两者都保留数据插入List的顺序。所以在这种情况下没有其他方法,你必须逐个迭代。
替代解决方案设置。经常使用三种类型的集合,它们是TreeSet,HashSet和LinkedHashSet。
LinkedHashSet :保留插入数据集的顺序。 (在你的情况下没用)。搜索将在O(n)。
TreeSet :它在内部维护红黑树中的数据。所以搜索会很快。搜索将在O(log n)。
HashSet :它在内部维护HashMap中的数据。因此搜索将比TreeSet快得多。搜索将在O(1)。
答案 3 :(得分:0)
由于地图不在等式中而您需要使用列表,因此您最终会进行那么多次迭代。或者,您可以对列表进行排序并实现类似逻辑的二进制搜索,以获得更好的性但是,如果您对List不是很了解,可以使用HashSet。它在大多数方面类似于列表,但只能包含唯一值。文档说这个类为基本操作(添加,删除,包含和大小)提供恒定的时间性能。但为此,您需要覆盖与rollNo相关的equals和hashCode方法。实施例
public class Student {
private int rollNo;
private String name;
//Getters & Setters.
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + rollNo;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (rollNo != other.rollNo)
return false;
return true;
}
}
答案 4 :(得分:0)
好吧,如果你需要使用LinkedList
,为了提高性能,我唯一想到的就是将列表的大小除以2,并检查你正在寻找的索引for是在上限或下限范围内。
如果它在上半部分,则使用descendingIterator()
以相反的顺序迭代集合。如果它在下半部分,则使用正常iterator
。它不会提高它的性能,但至少当你想要一个上半部分的对象时,你会节省很多次迭代。毕竟,这是一个双重链表。
但是,我会使用Map
的实现,但由于你不能这样做,试试我所解释的。
答案 5 :(得分:0)
看起来roll no是唯一的。为什么不将它用作链表中的索引呢?将98卷没有对象放在链表的第98个索引中。
顺便说一下hashmap也没关系。虽然如果roll no是唯一的,那么上述方式在内存上既快又便宜。
答案 6 :(得分:0)
由于您目前通过简单的for循环添加学生,所有学生都很好,整齐排序。所以你可以说,位置x的学生的卷号是x + 1。
但现在想象一下,有些学生会离开而有些人会来。过了一段时间,&#34; x + 1&#34;不再起作用了。甚至连序列都不会再成为现实。所以它不再是1,2,3,而是2,3,1?
在具有> 1百万条目的集合上进行迭代,排序等是没用的。
您需要做的是:使用数据库! 如果您不能使用基于服务器的数据库,您也可以使用SQLite或类似的。
然后,您可以通过简单的SQL语句访问卷号为99(或943,251)的学生记录,并将结果解析为Student实例。
在我看来,这是保持代码相对容易和小的最快方法。
答案 7 :(得分:0)
如果您仅限于LinkedList
,则可以通过不使用get(i)
循环来升级代码。这种方法非常低效,因为如
Why would iterating over a List be faster than indexing through it?
每个get(i)
从列表的开头迭代到i-th
元素,如
得(0) - item0
得到(1) - item0 -> item1
得到(2) - item0 -> item1 -> item2
得到(3) - item0 -> item1 -> item2 -> item3
您应该使用Iterator
及其next
方法来获取基于前一个元素的下一个元素,而不是这种方法。代码如
Iterator<Student> it = list.iterator();
while ( it.hasNext() ){
Student s = i.next();
//handle s here - test it or something
}
会以这种方式迭代
next next next next
-> item0 -> item1 -> item2 -> item3
而不是
get(0) get(1) get(2) get(3)
-> item0 -> (item0->item1) -> (item0->item1->item2) -> (item0->item1->item2->item3)
上面的BTW代码也可以使用for-each loop编写
for (Student s : list){
//handle s here
}
所以改变你的
for(int i=0; i<listLength; i++){
if(list.get(i).getRollNo() == rollNo)
return list.get(i);
到
for(String s : list)
if (s.getRollNo() == rollNo)
return s;
如果您确定该列表是有序的,那么您可以通过使用ListIteratot
及其previous
方法(如
ListIterator<String> it = list.listIterator(list.size());
while(it.hasPrevious())
System.out.println(it.previous());