我是Java的初学者.请建议可以/应该使用哪些集合来维护Java中的排序列表.我曾尝试Map和Set,但他们不是我所期待的.
我正在寻找一个很好的java排序列表.谷歌搜索给我一些关于使用TreeSet/TreeMap的提示.但是这些组件缺少一件事:随机访问集合中的元素.例如,我想访问有序集合中的第n个元素,但是使用TreeSet,我必须遍历其他n-1个元素才能到达那里.这将是一种浪费,因为我的Set中有多达数千个元素.
基本上,我正在寻找类似于.NET中的排序列表的东西,能够快速添加元素,快速删除元素,并且可以随机访问列表中的任何元素.
在某处实现了这种排序列表吗?谢谢.
编辑
我对SortedList的兴趣源于这些问题:我需要维护一个包含数千个对象的列表(并且可以增长到数十万个).这些对象将持久保存到数据库中.我想从整个列表中随机选择几十个元素.因此,我尝试维护一个分离的内存列表,其中包含所有对象的主键(长号).当从数据库添加/删除对象时,我需要从列表中添加/删除键.我现在正在使用ArrayList,但是当记录数量增长时,我担心ArrayList不适合它.(想象一下,每次从数据库中删除对象时,都必须迭代数十万个元素).回到我编写.NET编程的时候,我会使用一个排序的List(List是一个.NET类,一旦Sorted属性设置为true,将维护其元素的顺序,并提供帮助删除/插入元素的二进制搜索很快).我希望我能从java BCL找到类似的东西,但不幸的是,我没有找到一个很好的匹配.
为什么只有一个SortedList<TKey, TValue>看起来更像是字典,但SortedList<T>实际上只是一个总是排序的列表?
根据有关SortedList的MSDN文档,它实际上是在内部实现为动态大小的数组KeyValuePair<TKey, TValue>,始终按键排序.作为任何类型的列表,同一个类不会更有用T吗?那个名字也不合适吗?
我想知道,如果流(或收集器)中已经有一个已实现的功能,它已将列表排序为值.例如,以下代码均生成按年龄分类的按性别分组的人员列表.第一个解决方案有一些开销排序(看起来有点邋)).第二个解决方案需要两次看每个人,但是以一种漂亮的方式完成工作.
首先排序然后在一个流中分组:
Map<Gender, List<Person>> sortedListsByGender = (List<Person>) roster
.stream()
.sorted(Person::compareByAge)
.collect(Collectors.groupingBy(Person::getGender));
Run Code Online (Sandbox Code Playgroud)
首先分组,然后对每个值进行排序:
Map<Gender, List<Person>> sortedListsByGender = (List<Person>) roster
.stream()
.collect(Collectors.groupingBy(Person::getGender));
sortedListsByGender.values()
.forEach(list -> Collections.sort(list, Person::compareByAge));
Run Code Online (Sandbox Code Playgroud)
我只是想知道,如果已经有一些实现的东西,它会在一次运行中完成,例如groupingBySorted.
有人能告诉我何时以及为何使用TREEMAP.我经历了这个链接, 但没有找到我的答案.
根据我的想法,我们使用treemap根据您的密钥获取数据,我们也可以通过其他方式实现.
我需要一个Collection对元素进行排序,但不会删除重复项.
我已经去了TreeSet,因为TreeSet实际上将值添加到支持TreeMap:
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
Run Code Online (Sandbox Code Playgroud)
TreeMap使用Comparators compare逻辑删除重复项
我写了一个Comparator在相同元素的情况下返回1而不是0.因此,在相同元素的情况下,TreeSet使用它Comparator不会覆盖副本,只会对其进行排序.
我已经测试了它的简单String对象,但我需要一组自定义对象.
public static void main(String[] args)
{
List<String> strList = Arrays.asList( new String[]{"d","b","c","z","s","b","d","a"} );
Set<String> strSet = new TreeSet<String>(new StringComparator());
strSet.addAll(strList);
System.out.println(strSet);
}
class StringComparator implements Comparator<String>
{
@Override
public int compare(String s1, String s2)
{
if(s1.compareTo(s2) == 0){
return 1;
}
else{
return s1.compareTo(s2);
}
}
} …Run Code Online (Sandbox Code Playgroud) 我们知道我们可以使用
Collections.sort
Run Code Online (Sandbox Code Playgroud)
在插入所有元素后对列表进行排序.
但如果元素一次插入一次,也许SortedMap更有效?
虽然,SortedMap缺乏subList方法.
我需要的是SortedMap能够有效地多次插入少量元素的东西,并且总是可以通过Comparator接口从上到下获得1~1000个子列表.
有什么建议吗?
假设我正在构建一个TreeSet对象,其顺序仅取决于一个值。
我不能做
TreeSet<Foo> tree = new TreeSet<>(Comparator.comparingInt(Foo::getX));
Run Code Online (Sandbox Code Playgroud)
因为如果我添加两个Foo具有相同对象的不同对象x,那么一个将替换另一个(即,如果我这样做,tree.add(foo1)并且,将代替)。tree.add(foo2)tree.size()12
我可以比较 的每个字段Foo,但我希望 的两个实例Foo被视为不同,即使每个字段都相同。
一种“几乎有效”的解决方案是
TreeSet<Foo> tree = new TreeSet<>(Comparator.comparingInt(Foo::getX).thenComparing(Foo::hashCode));
Run Code Online (Sandbox Code Playgroud)
但当存在哈希冲突时,这会失败。
总之,我正在寻找类似的东西
TreeSet<Foo> tree = new TreeSet<>(Comparator.comparingInt(Foo::getX).thenComparing(Foo::getInternalAddress));
Run Code Online (Sandbox Code Playgroud)
但我们当然无法使用这样的方法。
我知道有解决方法:
TreeMap<Foo, Integer>(并比较所有字段)来给出Foo特定对象的数量xTreeMap<Foo, List<Foo>>(或TreeMap<Integer, List<Foo>>键为x)。但如果“重复”的 foo 很少,那么所有单例列表都会浪费空间。因此,虽然我知道 a 有解决方法TreeMap,但我仍然想知道是否有一种方法可以仅使用 a 来做到这一点TreeSet。
有没有办法用两个或更多其他元素替换列表中的单个元素而不会打扰列表的其余部分?我知道你可以用另一个元素替换一个元素,但我正在寻找要添加的多个元素.用例是我想根据特定条件将给定元素拆分为两个或多个元素.
例如:假设列表包含图表上从节点A到节点F的路径,如下所示:A -> B -> C -> D -> E -> F
我想将节点C替换为另外两个元素,例如节点X和节点Y.最终列表应如下所示:
A -> B -> X -> Y -> D -> E -> F
注意:我仍然在考虑实现,但我还没有最终确定使用任何特定类型的列表(ArrayList,LinkedList等).
public class ArrayOfArrayList {
public static void main(String[] args) {
List<Date> dateList1 = new ArrayList<Date>();
List<Date> dateList2 = new ArrayList<Date>();
Calendar cal = new GregorianCalendar();
for(int i = 0; i < 5; i++) {
Date d1 = new Date();
cal.setTime(d1);
cal.add(Calendar.DATE, i);
dateList1.add(cal.getTime());
}
System.out.println(" *************** Date List 1st ****************");
for(Date date1 : dateList1) {
System.out.println("1stList"+date1);
}
System.out.println(" *************** Date List 1st ****************");
for(int i = 2; i < 8; i++) {
Date d2 = new Date();
cal.setTime(d2);
cal.add(Calendar.DATE, i); …Run Code Online (Sandbox Code Playgroud) 我正在运行一种相当直接的方法,它按字母顺序将单词添加到列表中。
出于某种原因,每当“addToData”方法结束时,它不会返回到主方法中的原始调用者,而是一起停止。
我已经调试了代码,它没有进入任何无限循环,也没有遇到异常。
主要方法:
// Create the first list, with empty constructor
TextList list0 = new TextList();
// Check the method - addToData
System.out.println(list0);
list0.addToData("hello");
System.out.println("list0 after adding the word hello: \n"+list0);
list0.addToData("hello");
System.out.println("list0 after adding the word hello twice: \n"+list0);
Run Code Online (Sandbox Code Playgroud)
我陷入困境的方法:
public void addToData(String word){// O(n) -> Because we are going over the whole list only once (n times)
if("".equals(word))
return;
if(_head == null) {
_head = new WordNode(word);
return;
}
WordNode temp = _head;
int n = 0; …Run Code Online (Sandbox Code Playgroud) java ×10
collections ×4
sorting ×2
treemap ×2
treeset ×2
.net ×1
arraylist ×1
comparator ×1
duplicates ×1
java-stream ×1
list ×1
sortedlist ×1
union ×1