黑马程序员技术交流社区

标题: map中值的排序问题 [打印本页]

作者: 盛亚昆    时间: 2012-3-30 12:06
标题: map中值的排序问题
import java.util.*;
import java.io.*;
public class Map1 {

        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                String s=charCount("abadcdffbaeba");
               
                System.out.println(s);
        }
        public static String charCount(String str){
                char[]chs=str.toCharArray();//把字符串转成字符数组
        TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
                int count=0;
                for (int x=0;x<chs.length;x++){
                        Integer value=tm.get(chs[x]);
                        if(value!=null)
                                count=value;
                        count++;
                        tm.put(chs[x], count);
                        count=0;
                }
       
                ArrayList<Map.Entry<Character,Integer>> infoidsList=  
            new ArrayList<Map.Entry<Character,Integer>>(tm.entrySet());  //这里是什么意思啊,高手指点
         
        Collections.sort(infoidsList,new MyCompare());  
        StringBuilder sBuilder=new StringBuilder();  
         
        for (int i = 0; i < infoidsList.size(); i++) {  
           
            sBuilder.append(infoidsList.get(i).getKey()+":"+infoidsList.get(i).getValue().toString()+",");  
        }  
         
        String result=sBuilder.deleteCharAt(sBuilder.length()-1).toString();  
         
        return result;  
  
    }  
       
        class MyCompare implements Comparator//类要实现这个接口
        {
         public int compare(Object  o1, Object o2)
     {
                 Map.Entry<Character, Integer> m1= (Map.Entry<Character, Integer>)o1;
                 Map.Entry<Character, Integer> m2= (Map.Entry<Character, Integer>)o2;
            
                        return m2.getValue().compareTo(m1.getValue());
     }
}
       
}

我要进行map数组中按值排序,做不出来了,高手指点
a.java:3: 类 Map1 是公共的,应在名为 Map1.java 的文件中声
public class Map1 {
       ^
a.java:42: 无法从静态上下文中引用非静态 变量 this
        Collections.sort(infoidsList,new MyCompare());
                                     ^
注意:a.java 使用了未经检查或不安全的操作。
注意:要了解详细信息,请使用 -Xlint:unchecked 重新编译。
作者: 龚龙    时间: 2012-3-30 12:31
本帖最后由 龚龙 于 2012-3-30 12:56 编辑

   ArrayList<Map.Entry<Character,Integer>> infoidsList=  
            new ArrayList<Map.Entry<Character,Integer>>(tm.entrySet());  //这里是什么意思啊,高手指点

tm.entrySet()的意思是,将tm(Map)集合中的键值对存放到Set集合中,就是说把键值对看成一个整体放到Set中去了.
Collcetions.sort(infoidsList,new MyComparator());  

比较器写成这样就行了,你为什么还要放到StringBuilder中去,多此一举!Entry也是Object的子类啊,也可以比较的!
你的比较器单独弄一个文件或放到Map1的外面,你那样写是Map1的内部类.
public class MyComparator implements Comparator<Entry<Character,Integer>> {


        @Override
        public int compare(Entry<Character, Integer> o1,
                        Entry<Character, Integer> o2) {
                int gap1 = o1.getKey() - o2.getKey();               //比较Key的差值
                int gap2 = o1.getValue() - o2.getValue();          //比较Value的差值
                return gap2 == 0? gap1 : gap2;                     //如果Value一样,就返回Key的差值,否则返回Value的差值
        }

}

作者: 郑洋洋    时间: 2012-3-30 12:50
ArrayList<Map.Entry<Character,Integer>> infoidsList=  
            new ArrayList<Map.Entry<Character,Integer>>(tm.entrySet());  
这里是你吧tm中的键值对放到了ArrayList中。

Collections.sort(infoidsList,new MyCompare());  这里的错误是,MyCompare是内部类,你都外部类都没有对象,你就要去创建内部类,肯定不能完成

作者: newlaw2013    时间: 2012-3-30 12:58
你上面的这段代码有一个编译错误和编译警告
1.编译错误:你在静态方法charCount()中访问了非静态的内部能成员MyCompare,错误代码 Collections.sort(infoidsList,new MyCompare());
解决办法是在MyCompare类之前加上static修饰符。
2.编译警告:由于你在定义比较器的时候没有写泛型参数 导致你在上面的错误代码中引用infoidsList变量的时候,发出编译警告,正确的写法:class MyCompare implements Comparator<Map.Entry<Character,Integer>>//类要实现这个接口,而且加上这个泛型参数后,在这个比较的compare方法中就不用再做类型强制转换了。你现在的代码是要做Object强制转换的。
3.ArrayList有一个重载的构造方法可以接收一个Collection的集合,构造一个ArrayList对象:ArrayList(Collection<? extends E> c),而tm.entrySet()就是返回一个Map.Entry<Character,Integer>类型的Set集合,就是将tm(Map)集合中的键值对存放到Set集合中,就是说把键值对看成一个整体放到Set中去。
由于Collections.sort()方法只接收一个List集合进行排序所以你这个地方需要把Set集合转换成List集合。
public static <T> void sort(List<T> list,Comparator<? super T> c)

  
作者: yangshang1    时间: 2012-3-30 13:03
import java.util.*;

class MyCompare implements Comparator<Map.Entry<Character, Integer>>//类要实现这个接口
{
  public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2)
      {
       //   Map.Entry<Character, Integer> m1= (Map.Entry<Character, Integer>)o1;
        //  Map.Entry<Character, Integer> m2= (Map.Entry<Character, Integer>)o2;
      
                return o1.getValue().compareTo(o2.getValue());
      }
}
public class Map1 {

        /**
          * @param args
          */
         public static void main(String[] args) {
                 // TODO Auto-generated method stub
                 String s=charCount("abadcdffbaeba");
                 
                System.out.println(s);
         }
         public  static String charCount(String str){
                 char[]chs=str.toCharArray();//把字符串转成字符数组
         TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
                 int count=0;
                 for (int x=0;x<chs.length;x++){
                         Integer value=tm.get(chs[x]);
                         if(value!=null)
                                 count=value;
                         count++;
                         tm.put(chs[x], count);
                         count=0;
                 }
              Set set=tm.entrySet();
                ArrayList<Map.Entry<Character,Integer>> infoidsList=  
             new ArrayList<Map.Entry<Character,Integer>>(set);  //这里是什么意思啊,高手指点
               
        Collections.sort(infoidsList,new MyCompare());  
         StringBuilder sBuilder=new StringBuilder();  
           
        for (int i = 0; i < infoidsList.size(); i++) {  
            
             sBuilder.append(infoidsList.get(i).getKey()+":"+infoidsList.get(i).getValue().toString()+",");  
         }  
           
        String result=sBuilder.deleteCharAt(sBuilder.length()-1).toString();  
           
        return result;  
   
     }  

         
}


作者: 乔玉吉    时间: 2012-3-30 14:00
1,ArrayList<Map.Entry<Character,Integer>> infoidsList=  
            new ArrayList<Map.Entry<Character,Integer>>(tm.entrySet());
  这句话是ArrayList的一个构造方法 ,ArrayList(Collection<? extends E> c) ,把一个集合作为构造方法的参数传进去的 ,tm.entrySet()就是返回一个包含隐射关系的Set集合

2,a.java:3: 类 Map1 是公共的,应在名为 Map1.java 的文件中声名,你可能保存的文件名不是Map1.java,因为如果类A被声明为公共的(public),那么必须将类A保存在名为A.java的文件中;



3,一般情况下都是把比较器放在一个单独的类中,你把比较器放在来Map1中了,变成了内部类,
非静态内部类的情况下,创建内部类对象时必须先创建一个外部类对象 new 外部类名().new 内部类名()     
所以Collections.sort(infoidsList,new MyCompare());  这句new MyCompare()会出错,然后就提示了 (a.java:42: 无法从静态上下文中引用非静态 变量 this)

4,你的比较器在实现 Comparator的时候没有用到泛型,所以会提示 注意:a.java 使用了未经检查或不安全的操作。   用了泛型就不需要用Object了 就不需要强转了,这就是泛型的好处.
作者: 盛亚昆    时间: 2012-3-30 15:02
3,一般情况下都是把比较器放在一个单独的类中,你把比较器放在来Map1中了,变成了内部类,
非静态内部类的情况下,创建内部类对象时必须先创建一个外部类对象 new 外部类名().new 内部类名()     
所以Collections.sort(infoidsList,new MyCompare());  这句new MyCompare()会出错,然后就提示了 (a.java:42: 无法从静态上下文中引用非静态 变量 this)

那这里怎么 弄啊,高手指点
作者: 何万县    时间: 2012-3-30 15:10
使用Map.Entry类,可以同时得到键和值的信息。

先看标准的Map访问方法如下:




[java] view plaincopy
01.Set keys = map.keySet( );  
02.        if(keys != null) {  
03.            Iterator iterator = keys.iterator( );  
04.            while(iterator.hasNext( )) {  
05.                Object key = iterator.next( );  
06.                Object value = map.get(key);  
07.                ....;  
08.            }  
09.        }  




然后,这个方法有一个问题。从Map中取得关键字之后,我们必须每次重复返回到Map中取得相对的值,这是很繁琐和费时的。

幸运的是,这里有一个更加简单的途径。Map类提供了一个称为entrySet()的方法,这个方法返回一个Map.Entry实例化后的对象集。接着,Map.Entry类提供了一个getKey()方法和一个getValue()方法,因此,上面的代码可以被组织得更符合逻辑。举例如下:




[java] view plaincopy
01.Set entries = map.entrySet( );  
02.        if(entries != null) {  
03.            Iterator iterator = entries.iterator( );  
04.            while(iterator.hasNext( )) {  
05.                Map.Entry entry =iterator.next( );  
06.                Object key = entry.getKey( );  
07.                Object value = entry.getValue();  
08.                ;....  
09.            }  
10.        }  




尽管增加了一行代码,我们却省略了许多对Map不必要的“get”调用。同时,提供给开发人员一个同时保持了关键字和其对应的值的类。Map.Entry同时也提供了一个setValue()方法,程序员可以使用它修改map里面的值。




[java] view plaincopy
01.Map<String, Integer> map = new TreeMap<String, Integer>();  
02.        map.put("j2se", 20);   
03.        map.put("j2ee", 10);   
04.        map.put("j2me", 30);  
05.        List<Map.Entry<String, Integer>> infoIds = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());   
06.        //排序前   
07.        for (int i = 0; i < infoIds.size(); i++) {   
08.            String id = infoIds.get(i).toString();   
09.            System.out.println(id);   
10.        }   
11.        //排序   
12.        Collections.sort(infoIds, new Comparator<Map.Entry<String, Integer>>() {   
13.            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {   
14.                return (o2.getValue() - o1.getValue());   
15.            }   
16.        });   
17.        //排序后   
18.        for (int i = 0; i < infoIds.size(); i++) {   
19.            String id = infoIds.get(i).toString();   
20.            System.out.println(id);   
21.        }   
22.        排序前:   
23.        j2ee=10   
24.        j2me=30   
25.        j2se=20   
26.        排序后:   
27.        j2me=30   
28.        j2se=20   
29.        j2ee=10   






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2