您的位置:首页 > 运维架构 > 网站架构

Java集合架构及排序输出问题

2015-05-02 11:13 288 查看

概述

本文的写作动机来源于博主项目编码实践过程中的一个编码需求:

- 如何统计一段文本中的词频并按词频降序输出。

本文针对这一需求给出了三种主要的解决方案:

自定义类Term 并借助于Collections.sort(list, comparator)方法

使用HashMap和Collections.sort(list, comparator)方法

用比较器初始化TreeMap(Comparator)实现

Java集合架构概述

Java集合架构即Collection接口,根据集合论的基本定义,集合(Collection)即为一个存储一组元素(Element)的容器. Java Collection支持三种类型集合,一般书上喜欢翻译成: ’ 规则集(Set)’,’ 线性表(List)’和’ 图(Map)’。博主认为更应该翻译成: ’ 集合(Set)’,’ 线性表(List)’和’ 映射/键值对(Map)’。

集合(Set)

按理来说,Set接口才能算是集合论意义上的“集合”,因为Collection中的元素(Element)是可以相同的,而Set接口扩展Collection接口,虽然没有引入任何新的变量和方法,但Set规定了其中的元素(Element)不能重复,即不能存在相同的元素,而元素是否相同由‘equals()’函数定义,Set中不可能同时存在元素 e1和e2, 使得 ‘e1.equals(e2)’。而如果我们将多个相同的元素添加到集合Set中,将只有一个会被存储。

集合Set的三个具体类是HashSet,LinkedHashSet和TreeSet.

散列集HashSet

HashSet中的元素是没有特殊顺序的,要给它们排序,需要使用 链式散列集LinkedHashSet 或 树形集TreeSet。

链式散列集LinkedHashSet

链式散列集LinkedHashSet 使用链表实现对 HashSet 类的扩展,元素在LinkedHashSet中存储时保持插入的顺序,即在LinkedHashSet中,元素只能按照它们插入LinkedHashSet的顺序进行排序和提取。要实现按照用户自定义的序提取,比如文章一开始提到的按照词频降序,就需要使用树形集TreeSet了。

树形集TreeSet

线性表(List)

映射/键值对(Map)

Java集合架构实现词频降序输出

方案一:自定义Term类

该方案首先定义自己的词类Term, 并覆盖比较函数compareTo(Term term):

[code]import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

/**
 * @author darthy
 * weibo: http://weibo.com/u/1776952043?wvr=5&lf=reg  * 2015-05-02
 */
public class Term implements Comparable<Term>{

    private String wordName;
    private int wordCount = 0;
//  private double wordFreq = 0;       // 预留归一化的词频
//  private double tfidf = 0;          // 预留TF-IDF

    public Term(){

    }

    public String getWordName(){
        return this.wordName;
    }
    public void setWordName(String wordName){
        this.wordName = wordName;
    }

    public int getWordCount(){
        return this.wordCount;
    }
    public void setWordCount(int wordCount){
        this.wordCount = wordCount;
    }

    /**实现比较函数*/
    @Override
    public int compareTo(Term o) {
        if (this.getWordCount() > o.getWordCount())
            return 1;                            // 大于
        else if(this.getWordCount() < o.getWordCount())
            return -1;                           // 小于
        else
            return 0;
    }

    /** 根据wordCount升序排序的比较器内部类 */
    public static class TermComparatorByCount implements Comparator<Term>{
        @Override
        public int compare(Term o1, Term o2) {
            return o1.compareTo(o2);
        }   
    }
}


然后定义自己的比较器(Comparator)

[code]


最后将文本的Term装入List中,并使用Collections.sort()方法排序

[code]/** Test Main  */
    public static void main(String[] args) {

        String text = "have a good day 我是 中文 分词 后 的 文本 以 空格 分隔  统计 中文 and English" +
                " today is a very sunny day 分词 空格 中文 都 加 一倍 再 加 一个 专利";
        text = text.trim();

        String[] words = text.split(" ");
        for ( int i=0; i<words.length; i++){
            if (words[i].length() > 1){
                if (hashMap.get(words[i]) != null ){
                    int value = hashMap.get(words[i]).intValue();      // 获取词频
                    value++;                                                                         // 词频+1
                    hashMap.put(words[i], value);                                // 覆盖添加
                }
                else{
                    hashMap.put(words[i], 1);      
                }
            }
        }

        ArrayList<Map.Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>();     // 存放<String, Integer>对象放入List中
        list.addAll(hashMap.entrySet());

        MapEntryComparator myComparator = new MapEntryComparator();      // 创建Entry排序器对象
        Collections.sort(list, Collections.reverseOrder(myComparator) );            // 使用Entry排序器对list进行排序
        }


方案二:使用映射HashMap

首先使用HashMap

[code]String text = "have a good day 我是 中文 分词 后 的 文本 以 空格 分隔  统计 中文 and English" +
                " today is a very sunny day 分词 空格 中文 都 加 一倍 再 加 一个 专利";
        text = text.trim();

        String[] words = text.split(" ");
        for ( int i=0; i<words.length; i++){
            if (words[i].length() > 1){
                if (hashMap.get(words[i]) != null ){
                    int value = hashMap.get(words[i]).intValue();      // 获取词频
                    value++;                                                                         // 词频+1
                    hashMap.put(words[i], value);                                // 覆盖添加
                }
                else{
                    hashMap.put(words[i], 1);      
                }
            }
        }


然后定义对键值对Map.Entry

[code]public class MapEntryComparator implements Comparator<Object>{

        @Override
        public int compare(Object o1, Object o2) {
            Map.Entry<String, Integer> e1 = (Map.Entry<String, Integer>) o1;
            Map.Entry<String, Integer> e2 = (Map.Entry<String, Integer>) o2;
            return e1.getValue().compareTo(e2.getValue());        // 按照Integer的正常升序排序
        }       
    }


最后将HashMap装入List中,并使用Collections.sort()方法排序

[code]/** Test Main  */
    public static void main(String[] args) {

        ArrayList<Map.Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>();     // 存放<String, Integer>对象放入List中
        list.addAll(hashMap.entrySet());

        MapEntryComparator myComparator = new MapEntryComparator();      // 创建Entry排序器对象
        Collections.sort(list, Collections.reverseOrder(myComparator) );            // 使用Entry排序器对list进行排序
        }


总结

Java集合架构是Java2 新增的非常强大和好用的功能,更多介绍可参考博文 http://blog.sina.com.cn/s/blog_3fb3625f0101aref.html

写博不易,转载请注明来源:http://blog.csdn.net/dachylong

若文章存在错误之处,请大家不吝赐教!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: