set,map,list集合的特点及其排序的方法 Set集合排序 LinkedHashMap的特性:

特点:
list:存储: 有序的 可重复的
访问:可以for循环,foreach循环,iterator迭代器 迭代。
set:存储:无序的 不重复的
访问:可以foreach循环,iterator迭代器 迭代
map:存储:存储的是一对一对的映射 ”key=value“,key值 是无序,不重复的。value值可重复
访问:可以map中key值转为为set存储,然后迭代这个set,用map.get(key)获取value
也可以 转换为entry对象 用迭代器迭代




Set集合排序

TreeSet使用元素的自然顺序对元素进行排序,或者根据创建set时提供的Comparator进行排序,具体取决于使用的构造方法。通俗一点来说,就是可以按照排序后的列表显示,也可以按照指定的规则排序。

Set<String> set = new TreeSet<String>();       
        set.add("f");  
        set.add("a");  
        set.add("b");  
        set.add("c");  
        set.add("d");  
        set.add("e");          
        System.out.println(set);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出:[a, b, c, d, e, f] ,按照排序后输出

若想它倒序输出,可以指定一个规则让他倒序输出

public class TreeSetTest3 {  
     public static void main(String[] args) {  
        Set<String> set = new TreeSet<String>(new MyComparator());  
        set.add("a");  
        set.add("b");  
        set.add("c");  
        set.add("d");  
        set.add("e");  
        set.add("A");        
        for(Iterator<String> iterator = set.iterator();iterator.hasNext();){  
            System.out.print(iterator.next()+" ");  
        }  
    }  
}    
class MyComparator implements Comparator<String>{  
    @Override  
    public int compare(String o1, String o2) {           
        return o2.compareTo(o1);//降序排列  
    }  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

输出:e d c b a A

如果Set集合中放入的是我们自己定义的一个类类型呢?

注意:一定要定义一个排序规则类实现Comparator接口,与上面的方法类似

public class TreeSetTest2 {  
    public static void main(String[] args) {  
        Set<Person> set = new TreeSet<Person>(new PersonComparator());  
        Person p1 =  new Person(10);  
        Person p2 =  new Person(20);  
        Person p3 =  new Person(30);  
        Person p4 =  new Person(40);  
        set.add(p1);  
        set.add(p2);  
        set.add(p3);  
        set.add(p4);         
        for(Iterator<Person> iterator = set.iterator();iterator.hasNext();){  
            System.out.print(iterator.next().score+" ");  
        }  
    }  
}  
class Person{  
    int score;  
    public Person(int score){  
        this.score = score;  
    }     
    public String toString(){  
        return String.valueOf(this.score);  
    }  
}  
class PersonComparator implements Comparator<Person>{  
    @Override  
    public int compare(Person o1, Person o2) {      
        return o1.score - o2.score;  
    }      
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

输出:10 20 30 40

如果按照一个人的分数的倒序排列,只需要更改compare方法中的o2.score-o1.score

参考博客:http://blog.csdn.net/u014649337/article/details/43734863


扫描二维码关注公众号,回复: 1551649 查看本文章

LinkedHashMap的特性:

LinkedHashMap的特性

LinkedHashMap的特性:


   Linked内部含有一个private transient Entry header;来记录元素插入的顺序或者是元素被访问的顺序。利用这个线性结构的对象,可以帮助记录entry加入的前后顺序或者记录entry被访问的频率(最少被访问的entry靠前,最近访问的entry靠后)。大致的过程如下:

new LinkedHashMap(10, 0.75, true);
其中前面两个参数就是HashMap构造函数需要的参数,后面的true表明LinkedHashMap按照访问的次序来排序(即accessOrder为true)
按照访问的次序来排序的含义:当调用LinkedHashMap的get(key)或者put(key, value)时,碰巧key在map中被包含,那么LinkedHashMap会将key对象的entry放在线性结构的最后。
按照插入顺序来排序的含义:调用get(key), 或者put(key, value)并不会对线性结构产生任何的影响

正是因为LinkedHashMap提供按照访问的次序来排序的功能,所以它才需要改写HashMap的get(key)方法(HashMap不需要排序)和HashMap.Entry的recordAccess(HashMap)方法
public Object get(Object key) {
        Entry e = (Entry)getEntry(key);
        if (e == null)
            return null;
        e.recordAccess(this);
        return e.value;
    }

void recordAccess(HashMap m) {
            LinkedHashMap lm = (LinkedHashMap)m;
            if (lm.accessOrder) {
                lm.modCount++;
                remove();
                addBefore(lm.header);
            }
        }
注意addBefore(lm.header)是将该entry放在header线性表的最后。(参考LinkedHashMap.Entry extends HashMap.Entry 比起HashMap.Entry多了before, after两个域,是双向的)

至于put(key, value)方法, LinkedHashMap不需要去改写,用HashMap的就可以了,因为HashMap在其put(key, value)方法里边已经预留了e.recordAccess(this);

还有一个方法值得关注:
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return false;
    }
当调用put(key, value)的时候,HashMap判断是否要自动增加map的size的作法是判断是否超过threshold, LinkedHashMap则进行了扩展,如果removeEldestEntry方法return false;(默认的实现),那么LinkedHashMap跟HashMap处理扩容的方式一致;如果removeEldestEntry返回true,那么LinkedHashMap会自动删掉最不常用的那个entry(也就是header线性表最前面的那个)。

这会造成严重的性能问题吗?答案当然是否定的。因为在这儿的链表操作是常量级的。这也是LinkedHashMap/Set在这儿比TreeMap/Set性能更高的原因。

同样,LinkedHashMap/Set也不是thread-safe的。如果在多线程下访问,是需要进行外部同步,或者使用Collections.synchronizedMap()的方法包装成一个thread-safe的Map/Set。

特别需要注意的是,在使用“访问顺序”时,读取节点操作也是“结构变化”的操作。因为,这会改变元素遍历的顺序。所以,在使用LinkedHashMap的iterator()方法,遍历元素时,如果其它线程有读取操作,也要进行同步。否则,也会抛出同其它fail-fast一样的由于删除或增加操作而引起的CurrentModificationException的例外。
最后,LinkedHashMap缺省是使用插入顺序的,如何构造一个访问顺序的LinkedHashMap呢?很简单:public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) accessOrder = true 即可。




/**

 * 电子墨水屏安卓端查询学生课程按照排列顺


序将数据存储到list中


 */
@Override
public List<String> couList(List<UserCourseEntity> tUserCours) throws ParseException {
List<String> list = new ArrayList<String>();
Set<String> timeSet = new LinkedHashSet<String>();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
//遍历集合将上课时间与第几节课放进set中,定义Set<String> timeSet = new LinkedHashSet<String>();可以将set中的数据按照添加顺序存放
for (UserCourseEntity userCourseEntity : tUserCours) {
String startTime = sdf.format(sdf.parse(userCourseEntity.getStartTime()));
String endTime = sdf.format(sdf.parse(userCourseEntity.getEndTime()));
String periodNum = userCourseEntity.getPeriodNum();
String time = startTime+"~"+endTime;
boolean res = timeSet.add(time+"-"+periodNum);
if (!res) {
continue;
}
}
//遍历set集合与课程集合将第几节课与对应课程键值对关联定义LinkedHashMap<String,List<String>> map = new LinkedHashMap<String,List<String>>();也可以将数据按照添加顺序存放
LinkedHashMap<String,List<String>> map = new LinkedHashMap<String,List<String>>();
for (String str : timeSet) {
for (UserCourseEntity course : tUserCours) {
String ts = sdf.format(sdf.parse(course.getStartTime()))+"~"+sdf.format(sdf.parse(course.getEndTime()))+"-"+course.getPeriodNum();
if(ts.equals(str)){
List<String> couList = map.get(ts);
if(couList==null){
couList = new ArrayList<String>();
}
couList.add(course.getCourseName());
map.put(ts, couList);
}
}
}
//遍历map.keySet()与 map.get(key)分别按对应顺序放入list中
for (String key : map.keySet()) {
String periodNum = key.split("-")[1];
String time = key.split("-")[0];

list.add(periodNum);
list.add(time);
for (String courseName : map.get(key)) {
list.add(courseName);
}
}
return list;
}

}



对map集合进行排序

      今天做统计时需要对X轴的地区按照地区代码(areaCode)进行排序,由于在构建XMLData使用的map来进行数据统计的,所以在统计过程中就需要对map进行排序。

一、简单介绍Map

       在讲解Map排序之前,我们先来稍微了解下map。map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等。其中这四者的区别如下(简单介绍):

       HashMap:我们最常用的Map,它根据key的HashCode 值来存储数据,根据key可以直接获取它的Value,同时它具有很快的访问速度。HashMap最多只允许一条记录的key值为Null(多条会覆盖);允许多条记录的Value为 Null。非同步的。

      TreeMap: 能够把它保存的记录根据key排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。

      Hashtable: 与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。

      LinkedHashMap: 保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。

 

二、Map排序

TreeMap

      TreeMap默认是升序的,如果我们需要改变排序方式,则需要使用比较器:Comparator。

      Comparator可以对集合对象或者数组进行排序的比较器接口,实现该接口的public compare(T o1,To2)方法即可实现排序,该方法主要是根据第一个参数o1,小于、等于或者大于o2分别返回负整数、0或者正整数。如下:

复制代码
public class TreeMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new TreeMap<String, String>(
                new Comparator<String>() {
                    public int compare(String obj1, String obj2) {
                        // 降序排序
                        return obj2.compareTo(obj1);
                    }
                });
        map.put("c", "ccccc");
        map.put("a", "aaaaa");
        map.put("b", "bbbbb");
        map.put("d", "ddddd");
        
        Set<String> keySet = map.keySet();
        Iterator<String> iter = keySet.iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            System.out.println(key + ":" + map.get(key));
        }
    }
}
复制代码

      运行结果如下:

      d:ddddd 
      c:ccccc 
      b:bbbbb 
      a:aaaaa

      上面例子是对根据TreeMap的key值来进行排序的,但是有时我们需要根据TreeMap的value来进行排序。对value排序我们就需要借助于Collections的sort(List<T> list, Comparator<? super T> c)方法,该方法根据指定比较器产生的顺序对指定列表进行排序。但是有一个前提条件,那就是所有的元素都必须能够根据所提供的比较器来进行比较。如下:

复制代码
public class TreeMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new TreeMap<String, String>();
        map.put("d", "ddddd");
        map.put("b", "bbbbb");
        map.put("a", "aaaaa");
        map.put("c", "ccccc");
        
        //这里将map.entrySet()转换成list
        List<Map.Entry<String,String>> list = new ArrayList<Map.Entry<String,String>>(map.entrySet());
        //然后通过比较器来实现排序
        Collections.sort(list,new Comparator<Map.Entry<String,String>>() {
            //升序排序
            public int compare(Entry<String, String> o1,
                    Entry<String, String> o2) {
                return o1.getValue().compareTo(o2.getValue());
            }
            
        });
        
        for(Map.Entry<String,String> mapping:list){ 
               System.out.println(mapping.getKey()+":"+mapping.getValue()); 
          } 
    }
}
复制代码

      运行结果

      a:aaaaa 
      b:bbbbb 
      c:ccccc 
      d:ddddd

HashMap

      我们都是HashMap的值是没有顺序的,他是按照key的HashCode来实现的。对于这个无序的HashMap我们要怎么来实现排序呢?参照TreeMap的value排序,我们一样的也可以实现HashMap的排序。

复制代码
public class HashMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("c", "ccccc");
        map.put("a", "aaaaa");
        map.put("b", "bbbbb");
        map.put("d", "ddddd");
        
        List<Map.Entry<String,String>> list = new ArrayList<Map.Entry<String,String>>(map.entrySet());
        Collections.sort(list,new Comparator<Map.Entry<String,String>>() {
            //升序排序
            public int compare(Entry<String, String> o1,
                    Entry<String, String> o2) {
                return o1.getValue().compareTo(o2.getValue());
            }
            
        });
        
        for(Map.Entry<String,String> mapping:list){ 
               System.out.println(mapping.getKey()+":"+mapping.getValue()); 
          } 
     }
}
复制代码

      运行结果

      a:aaaaa 
      b:bbbbb 
      c:ccccc 
      d:ddddd

 

 



猜你喜欢

转载自blog.csdn.net/qq_41579101/article/details/80632984
今日推荐