Java:同步排列多个ArrayList或单个映射的ArrayList

问题描述:

我大约3个月前才开始学习Java,这是我的第一篇文章,所以请耐心等待。Java:同步排列多个ArrayList或单个映射的ArrayList

我有从解析的XML构建的多个ArrayList,它们按顺序直接相互关联。随后将数组放入单个映射的ArrayList(groupData)中,以便使用在Android GUI中创建列表的SimpleAdapter进行读取。

我想要做的是根据一个数组(arr_title)按字母顺序对列表进行排序,其他数组保持与其同步的顺序。只要最终显示的列表已排序,无论排序发生在何处。我认为最好在构建映射数组后进行排序。更简单或更容易理解的代码越好,但不希望排序也变得非常慢。每个阵列有大约140个对象,但考虑到XML是从网络中抽取的,可能会扩大。

我花了数小时搜索谷歌并尝试了一些进展甚微的事情。 Collections.sort(arr_title)会根据需要对一个数组进行排序,但其他数组不匹配,对其他数组做相同的处理显然只是按照我不需要的方式对它们进行排序。我注意到提及使用TreeMap类型和Comparator进行类似的排序,但是在这种情况下无法弄清楚如何使用它们,可能是因为这些例子没有提供足够大的图片让我理解。

下面的示例是大多数东西发生在独立阵列创建后的地方。

List<Map<String, String>> groupData = new ArrayList<Map<String, String>>(); 
Map<String, String> group; 

int item = 0; 
do { 
    group = new HashMap<String, String>(); 
    group.put("title", arr_title.get(item)); 
    group.put("desc", arr_desc.get(item)); 
    group.put("num", Integer.toString(arr_num.get(item))); 
    groupData.add(group); 
    item++; 
} while (item < arr_num.size()); 

SimpleAdapter adapter = new SimpleAdapter(this, groupData, android.R.layout.simple_list_item_2, new String[] {"title", "desc", "num"}, new int[]{android.R.id.text1, android.R.id.text2}); 
setListAdapter(adapter); 

我倾向于同意,使用比较器会更容易。

Comparator<HashMap<String, String>> comparator = new Comparator<HashMap<String, String>>() {          
     @Override 
     public int compare(HashMap<String, String> object1, HashMap<String, String> object2) 
     {  
       return object1.get("title").compareToIgnoreCase(object2.get("title")); 
     } 
};  
Collections.sort(groupData, comparator); 

“标题”是在散列密钥进行排序。

+0

我不知道为什么我以前无法弄清楚这一点,但它的作用像一个魅力,显然比我的解决方案更干净(而且我肯定快得多)。有时候我需要一个充分有效的例子来理解它是如何工作的。这个问题的原始项目已经被废弃(不是因为这个),但事实证明,我的几个项目中有一半需要在ArrayList中排序的HashMap。 – 2011-02-12 12:58:09

+0

顺便说一句,我不得不用你的例子中的适配器替换我的数组列表(在将它设置在适配器上之前)。 – 2011-02-12 13:09:17

+0

你说得对。我在代码段中更改了它。我打算把数组列表。谢谢! – VMcPherron 2011-02-14 18:22:51

这听起来像你已经犯了一个经典的初学者的错误(你可以原谅):没有足够的思维对象。

Java的一种面向对象的语言。在我看来,您的多个相关项目列表应该是单个的对象列表,每个对象列表都包含您当前放入多个列表的项目集。然后,您可以使用比较器按照您希望的方式对该对象列表进行排序。所有相关属性都很好地封装在它们所属的对象中。无论你如何分类,他们都会在一起。

对象都是关于封装和信息隐藏的。

欢迎来到SO。

首先,有一些Java约定来命名变量。其次,Java是一种面向对象的语言,所以你必须改变主意,关于你如何解决问题。

在这种特殊情况下,您希望将分布在3个数组中的所有数据放在一起。那么,为它创建一个类。

public class Data implements Comparable{ 
private String title; 
private String desc; 
private int num; 
public Data(String title, String desc, int num){ 
    //set the private fields here 
} 
//You may want to write some setters and getters here for individual fields. 

public int compareTo(Object o){ 
//here you compare an item with other item. Remember to cast the object o to Data. 
// Read http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Comparable.html to know what to return 
} 

} 

,然后在主类:

int item = 0; 
do { 
    Data group = new Data(arr_title.get(item),arr_desc.get(item),arr_num.get(item); 
    groupData.add(group); 
    item++; 
} while (item < arr_num.size()); 
Collections.sort(groupData); 

最后但并非最不重要的,有更好的方法,通过在Java中的一组进行迭代。阅读关于Iterators。这是一个更安全,更清洁的方式来通过一个数组或一组。

+0

虽然我对几种语言有很基础的知识,但我认为Java是我学到的第一门语言,所以我没有真正将技能从另一种语言转化为Java。我第一次开始学习Java时,我记得涉及面向对象的主题,但我想我没有花足够的时间去完全理解它,或者养成正确使用它的习惯。我想这是一个典型的问题,而不是上课。 我会给你的例子一个旋转,让你知道它是如何去。谢谢! – 2010-07-02 15:19:52

+0

不幸的是我似乎仍然有麻烦。 有一些警告,并且首先有一些错误,但在将第一行更改为列表 groupData = new ArrayList ();;移除Map 组;然后在SimpleAdapter中将groupData转换为列表>),我设法摆脱了错误和编译,但我在运行时得到一个ClassCastException。它似乎是由SimpleAdapter接受的列表类型引起的。我会继续讨论这个问题,但是会有更多的技巧值得赞赏。 – 2010-07-02 19:16:35

+0

是的,这是正常的,因为Java是一种严格的类型语言。你改变了数据的类型,所以它抱怨:)。 您现在要做的是修改SimpleAdapter以接收数据列表(列表)而不是旧的groupData。 – pakore 2010-07-04 20:19:31

我终于明白了!感谢一个更大的项目遇到类似的问题,基本上迫使我解决这个问题。除了某些更改的变量名称之外,此示例以外的所有内容大部分与原始帖子中的相同。我不确定这是否是最好的方法,但它能以非常可接受的速度完成工作,而且我可以真正理解它是如何工作的。

ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>(); 
// Put separated item details in a HashMap for each item, 
// then insert it in sorted order to list. 
for(int n = 0; n < arrayTitle.size(); n++) { 
    HashMap<String, String> item = new HashMap<String, String>(); 
    item.put("title", arrayTitle.get(n)); 
    item.put("desc", arrayDesc.get(n));  
    try { 
     int c, i = 0; 
     do { 
      // Compare new title with titles existing in list 
      // from beginning to end or until title is found that it goes before. 
      c = arrayTitle.get(n).compareTo(list.get(i).get("title")); 
      i++; 
     } while (c > 0 & i < list.size()); 
     i--; 
     if(c > 0) { 
      // New item goes after all others currently in list. 
      list.add(item); 
     } else if (c < 0) { 
      // New item goes before an item already in list. 
      list.add(i, item); 
     } 
    } catch (Exception e) { 
     // If nothing in list to compare with, add first item. 
     list.add(item); 
    } 
}  
SimpleAdapter adapter = new SimpleAdapter(this, list, android.R.layout.simple_list_item_2, new String[] {"title", "desc"}, new int[]{android.R.id.text1, android.R.id.text2}); 
setListAdapter(adapter); 
+0

也许对于后面的,但是看一下'Collections.sort'和“可比” - 通过这些,你可以在不编写排序代码的情况下做你所做的事情。你只是提示java *如何排序*(通过'compareTo'),而Collections.sort则为你排序。你不需要你的for和while循环。 – Nivas 2010-09-25 07:36:03

+0

这就是我以前想要做的,但我一定是做错了什么。我不明白如何使用ArrayList 以外的其他任何东西,并且使其与其他类型的工作似乎需要更多的编码(我不明白)比我在这里做的更好。如果你想把它交给我,我会接受一个有效的例子,但是因为我对我所拥有的东西满意,所以我现在不在意花更多的精力去想出如何使它更有效率。我相信我会想在这条路上进一步优化它。 – 2010-09-25 19:40:37