A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

刘深峰

初级黑马

  • 黑马币:6

  • 帖子:21

  • 精华:0

© 刘深峰 初级黑马   /  2012-6-15 01:19  /  4317 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

晕,都1点了,不知道还有人在吗。
请问怎么在TreeMap中按键保证唯一,按值排序?

如下所示:
TreeMap<String,Integer> tm = new TreeMap<String, Integer>();

自定义一个比较器行吗?如果行,应该怎么定义?如果不行,有什么方法可以实现我上面说的需求?

评分

参与人数 1技术分 +1 收起 理由
赵志勇 + 1 很给力!

查看全部评分

8 个回复

倒序浏览
package day1;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDemo {
   
        public static void main(String[] args) {
               
                TreeSet  tr = new TreeSet(new com());
               
                tr.add(new Student("lisi03",39));
                tr.add(new Student("lisi04",35));
                tr.add(new Student("lisi03",43));
                tr.add(new Student("lisi08",73));
               
                for(Iterator it =tr.iterator();it.hasNext();){
                       
                             
                            System.out.println(it.next().toString());
                }
               
        }
       
       
       
}
class Student{
       
       
          public Student(String name, int age) {
                super();
                this.name = name;
                this.age = age;
        }
        private String name;
          private int age;
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
        public int getAge() {
                return age;
        }
        public void setAge(int age) {
                this.age = age;
        }
        @Override
        public String toString() {
                return "Student [name=" + name + ", age=" + age + "]";
        }
}
class com  implements Comparator<Student>{  //这里我定义了一个比较器。

        @Override
        public int compare(Student o1, Student o2) {
       
       
            int num=o1.getName().compareTo(o2.getName());        //这里我是按键保证唯一性,
            if(num==0){  //  键和键比较会返回个值, 如果这个num值 == 0  的话就认为他们相等,就存不进去,就保证唯一性了。
            
                       return 0;
            }
            if(o1.getAge()>o2.getAge()){  //这里我是让他们的值进行排序。 如果是正数的话就是从小到大排序,反之是从大到小。
                   
                     return 1;
            }else{
                     return -1;
            }
               
                //return num;
               
        }


        /*if(o1.getAge()>o2.getAge())  
            return 1;
    if(o2.getAge()==o1.getAge())
              
               return 0;
    return -1;*/

}
你先参考下,如果不明白的地方可以回复,继续问我。我在帮你解答。。

评分

参与人数 1技术分 +1 收起 理由
赵志勇 + 1 很给力!

查看全部评分

回复 使用道具 举报
sunhaodi 发表于 2012-6-15 01:51
package day1;

import java.util.Comparator;

我程序中TreeMap的元素不是一个对象,只是两个单纯的基本类型String 和Integer,这样的话如何排序?谢谢~~
回复 使用道具 举报
是TreeMap,不是TreeSet
回复 使用道具 举报
TreeMap中存放的元素必须实现comparable接口  目的是为了在存放元素时就有排序性
我查过API,API中的 String Interge 等包装类底层都实现了comparable接口了 所以我们在存放这些元素本身就具有自然排序的能力。,若果这些基本数据类型排序不是你想要的,你就可以自定义一个比较器来改变排序的规则。
回复 使用道具 举报
package day1;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;

public class SortMapByValue {
public static void main(String[] args){
TreeMap<String,Integer> newMap=new TreeMap<String,Integer>();
newMap.put("aaa10", 1);
newMap.put("aaa9", 9);
newMap.put("aaa4", 4);
newMap.put("aaa7", 7);
newMap.put("aaa6", 6);
newMap.put("aaa3", 3);
newMap.put("aaa10", 10);


ByValueComparator bvc =new ByValueComparator(newMap);


List<String> newList=new ArrayList<String>(newMap.keySet());

Collections.sort(newList, bvc);

for(String str:newList){
       
System.out.println(str+".........................."+newMap.get(str));

}

}

/**
* @description
* 对Map按值进行排序
*  
* */
static class ByValueComparator implements Comparator<String> {

TreeMap<String, Integer> base_map;

public ByValueComparator(TreeMap<String, Integer> base_map) {

this.base_map = base_map;

}

public int compare(String arg0, String arg1) {

if (!base_map.containsKey(arg0) || !base_map.containsKey(arg1)) {

return 0;

}

if (base_map.get(arg0) < base_map.get(arg1)) {

return 1;

} else if (base_map.get(arg0) == base_map.get(arg1)) {

return 0;

} else {

return -1;

}

}

}

}

那就这个,哥们,你看这是你想要的了吧。也是自定义的比较器。
回复 使用道具 举报
public static void main(String[] args)
{
  TreeMap<String,Integer> tm = new TreeMap<String, Integer>();
          tm.put("a",1);
    tm.put("b",2);
    tm.put("c",3);
    System.out.println(tm);    //现在打印的是按自然顺序排列的元素,也就是{a=1,b=2,c=3}

}
而你现在不想按自然顺序排列,想按照自己的想法排的话,其实很简单,只要传入个比较器改写compare(T O1,T O2)方法即可,例如:
class comp implements Comparator<String>
{
public int compare(String s1,String s2)   //我现在改写了这个方法了
{
    return -1;
}
}
现在你把这个比较器传进去的话,打印后的结果就是{c=3,b=2,a=1}了。就记句一点,无论想怎么排序,只要在compare(T O1,T O2)这个方法上做文章就可以了。
compare(T O1,T O2)方法返回值:根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。

回复 使用道具 举报
sunhaodi 发表于 2012-6-15 02:41
package day1;

import java.util.ArrayList;

import java.io.*;
import java.util.*;
class password
{

public static void main(String[] args) throws IOException
{
  BufferedReader bufr = new BufferedReader(new FileReader("F:\\password.txt"));//文件里每行数据以( 用户名 # 密码 # 邮箱 )的格式存放着用户的账号信息
  String line = null;  
  TreeMap<String,Integer> tm = new TreeMap<String, Integer>();
  while((line=bufr.readLine())!=null)//读取一行数据
  {  
   
   String[] strTemp = line.split("#");//用#把读到的一行数据分割成3部分
   strTemp[1] = strTemp[1].trim();//只取中间的密码,并去掉两端的空格
   Integer value = tm.get(strTemp[1]);//判断TreeMap中是否有记录
   if(value==null)
   {
    tm.put(strTemp[1],1);//若没有则添加进TreeMap,值为1
   }
   else
   {
    value = value + 1;//若有,则值加1,再刷新TreeMap
    tm.put(strTemp[1],value);
   }
  
  }
  
  StringBuilder sb = new StringBuilder();
   FileWriter fw = new FileWriter("count.txt", true);//把TreeMap中的数据写入文件
  
  ByValueComparator bvc =new ByValueComparator(tm);
  List<String> newList=new ArrayList<String>(tm.keySet());
  Collections.sort(newList, bvc);
  for(String str:newList)
  {
   sb.append(str+"\t"+tm.get(str)+"\r\n");
   fw.write(sb.toString());
   fw.flush();
   sb.delete(0,sb.length());
   //System.out.println(str+".........................."+newMap.get(str));
  }

  /*while(it.hasNext())
  {
   Map.Entry<String, Integer> me = it.next();
   String str = me.getKey();
   Integer value = me.getValue();     
    sb.append(str+"\t\t"+value+"\r\n");  // 以( 密码\t密码出现的次数 )的格式写入
    fw.write(sb.toString());
    fw.flush();
    sb.delete(0,sb.length());  
  }*/
  fw.close();
  

}
static class ByValueComparator implements Comparator<String>
{
  TreeMap<String, Integer> base_map;
  public ByValueComparator(TreeMap<String, Integer> base_map)
  {
   this.base_map = base_map;
  }
  public int compare(String arg0, String arg1)
  {
   if (!base_map.containsKey(arg0) || !base_map.containsKey(arg1))
   {
    return 0;
   }
   if (base_map.get(arg0) < base_map.get(arg1))
   {
    return 1;
   }
   else if (base_map.get(arg0) == base_map.get(arg1))
   {
    return 0;
   }
   else
   {
    return -1;
  
   }
  }
}

}

直接套你的代码,报错Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!,是不是我哪错了,找了半天没找到,这是我的程序,目的是读取一个文件,文件里每行数据以( 用户名 # 密码 # 邮箱 )的格式存放着用户的账号信息,我的程序只统计所有用户密码出现的次数。然后再以( 密码\t密码出现的次数 )的格式写入一个文件里。

回复 使用道具 举报
李盼 中级黑马 2012-6-15 07:29:33
9#
本帖最后由 李盼 于 2012-6-15 07:31 编辑

TreeMap中是保证键的唯一性,同时也是按照键来排序,而不是按照值来排序,排序原理和确保键的唯一性都是和TreeSet来的原理一样,是通过键对象的实现compareTo方法或compare方法来比较!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马