标准库中的集合与映射

来源:互联网 发布:vue.js 实现网页下载 编辑:程序博客网 时间:2024/06/04 00:25

关于Set接口

    Set接口不允许重复元的Collection。由接口SortedSet给出的一种
特殊类型的Set保证其中的各项处于有序的状态。因为一个Set IS-A Collection,所以用于访问继承
Collection的List的项的方法也对Set有效。

    由Set所要求的一些独特的操作是一些插入/删除/以及(有效地)执行
基本查找的能力。对于Set,add方法如果执行成功则返回true,否则返回false,因为被添加的项已经存在。
保持各项已有序的状态的Set的实现是TreeSet。TreeSet类的基本操作花费对数最坏时间。

    默认情况下,排序假设TreeSet中项实现Comparable接口。另一种排序
可以调用Comparator实例化TreeSet来确定。例如,我们可以创建一个忽略大小写的程序然后进行插入
操作。在下面的代码中,Set 的大小为1。

//@CaseInsensitiveCompare 忽略大小写的函数  Set<String> s = new TreeSet<String>(new CaseInsensitiveCompare());  s.add("Hello"); s.add("HELLO");  system.out.println("The size is:" + s.size());

关于Map接口

    Map是一个接口,代表由关键字以及它们的值组成的一些项的集合。关键字
必须是唯一的,但是若干个关键字可以映射到一些相同的值。因此,值不必是唯一的。在SortedMap接口
中,映射中的关键字保持逻辑上的有序状态。SortedMap接口的一种实现是TreeMao类。Map的基本操作
包括isEmply/clean/size等方法,而且最重要的是包含下列方法:

//判断是否存在这样的key值  boolean contains(KeyType key);//查找对应的Key值来进行查找相应的内容值  ValueType get(keyType key);//添加对应的对象  ValueType put(KeyType key, ValueType value);

    通过一个Map迭代要比Collection复杂,因为Map不提供迭代器,而是
提供3种方法,将Map对象的视图作为Collection对象返回。由于这些视图本身就是Collection,
因此它们可以被迭代。

  set<KeyType> keySet();  Collection<Value>  values();  set<Map.Entry<KeyType, valueType>> entrySet();

    方法keySet和values返回简单的集合(这些关键字不包含重复元,因此
以一个Set对象形式返回)。这里的entyySet方法是作为一些项而形成的Set对象被返回(由于关键字是唯一的,
应此不存在重复项)。每一项由被嵌套的接口Map.Entry表示。对于类型Map.Entry的对象,其现有
的方法包括关键字/关键字的值//一起改变关键字的值:

  keyType getKey();  valueType getValue();  valueType setValue(ValueType newValue);

TreeSet和TreeMap的实现

    Java要求TreeSet和TreeMap支持基本的add、remove和contains
操作以对数最坏的情况时间完成。因此,基本实现方法就是平衡二叉查找树。一般来说,我们并不适用
AVL树,而是经常使用一些自顶向下的红黑树。

利用标注库中的TreeMap和TreeSet写一个实例

    通过改变第一个字母, 单词wine可以变成dine,fine,line,mine,
nine,oine或vine。通过改变里三个字母可以变成wind,wing,wink,wins。假设我们有一本词典,
由89000个不同长度的单词。
    最直接的方法是使用Map对象,其中关键字是单词,而关键字的值
是用一字母替换得到的单词集合。

代码演示部分

import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.TreeMap;public class Mapping_words {/* * 计算一个Map对象的函数, 该对象以一些单词作为关键字而已只在一个字母处不同的一列 * 单词作为关键字的值。该函数对一个89000单词的词典运行75秒(非常慢的一个方法,暴力搜索) */private static boolean oneCharOff(String word1, String word2){  if(word1.length() != word2.length())  //判断长度是否相等,如果长度不想等就返回false    return false;  int diffs = 0;  for(int i = 0; i < word1.length(); i++)    if(word1.charAt(i) != word2.charAt(i))      if(diffs++ > 1)   //必须有且仅有一个字母不相同, 如果有1个以上的字母不同那么久返回false        return false;  return diffs == 1;}/* * @key     首先会查找在m里面查找是否有对应key值的value集合 * @value */private static<keyType> void updata(Map<keyType, List<String>> m, keyType key, String value){  List<String> lst = m.get(key);    //获取value集合  //如果没有就添加  if(lst == null){    lst = new ArrayList<>();    m.put(key, lst);  }  //不管有没有最后都要添加进去  lst.add(value);}/* * 第一个算法:该算法的时间为75秒。采用的几乎是枚举。 */private static Map<String, List<String>> computeAdjacentWords_01(List<String> theWords){  Map<String, List<String>> adjWords = new TreeMap<>();  String[] words = new String[theWords.size()];  theWords.toArray(words);  for(int i = 0; i < words.length; i++)    for(int j = i + 1; j < words.length; j++)      if(oneCharOff(words[i], words[j])){        updata(adjWords, words[i], words[j]);        updata(adjWords, words[j], words[i]);      }  return adjWords;}/** * 首先我们知道, 一个不同长度的两个单词再怎么变换最终还是不一样, 所以使用了一个策略就是将长度不同的单词来进行划分区域 * 划分之后就减小了不必要的试探 * @param theWords  词典里面所有的单词 * 运行时间缩减到了16秒 */private static Map<String, List<String>> computeAdjacentWords_02(List<String> theWords){  Map<String, List<String>> adjWords = new TreeMap<>();  Map<Integer, List<String>> wordsByLength = new TreeMap<>();   //按长度来进行分组的  for(String w : theWords)    updata(wordsByLength, w.length(), w);  //对长度Map进行迭代  for(List<String> groupsWords : wordsByLength.values()){    String[] words = new String[groupsWords.size()];    groupsWords.toArray(words);    for(int i = 0; i < words.length; i++)      for(int j = i + 1; j < words.length; j++)        if(oneCharOff(words[i], words[j])){          updata(adjWords, words[i], words[j]);          updata(adjWords, words[j], words[i]);        }  }  return adjWords;}/** * 这是一种最优化的算法, 使用一些附加的映射!和前面一样, 首先按长度进行一个划分, 然后分别对每组进行计算。 * 这时,首先要找出像wine和nine这样的单词对, 他们除了第一个单词以外都是一样的。对于长度为4的每一个单词, * 一种做法是删除第一个字母, 留下一个三个字母的代表。这样就形成了一个Map,其中关键字为一种代表。 * @param theWords * @return */private static Map<String, List<String>> computeAdjacentWords_03(List<String> theWords){  Map<String, List<String>> adjWords = new TreeMap<>();  Map<Integer, List<String>> wordsByLength = new TreeMap<>();   //按长度来进行分组的  for(String w : theWords)    updata(wordsByLength, w.length(), w);  for(Map.Entry<Integer, List<String>> entry : wordsByLength.entrySet()){    //每个长度的集合    List<String> groupsWords = entry.getValue();    int groupNum = entry.getKey();    for(int i = 0; i < groupNum; i++){      Map<String, List<String>> repToWord = new TreeMap<>();      for(String str : groupsWords){        //每个rep为单词的代表        String rep = str.substring(0, i) + str.substring(i + 1);        updata(repToWord, rep, str);      }      for(List<String> wordClique : repToWord.values())        if(wordClique.size() >= 2)          for(String s1 : wordClique)            for(String s2: wordClique)              if(s1 != s2)                updata(adjWords, s1, s2);    }  }  return adjWords;}/** * 打印结果并且显示时间差 * @param map */public static void printHighChangeables(Map<String, List<String>> map){  long start = System.currentTimeMillis();  for(Map.Entry<String, List<String>> entry : map.entrySet()){    List<String> words = entry.getValue();    System.out.print(entry.getKey() + " (");    System.out.println(words.size() + "):");    for(String s : words)      System.out.print(" " + s);    System.out.println();  }  long end = System.currentTimeMillis();  System.out.println(end - start);}public static void main(String[] args) {  String[] words = {"wine", "wife", "wipe", "wire", "dine", "fine", "line",      "mine", "nine", "pine", "vine"};  List<String> list = new ArrayList<>();  for (String string : words) {    list.add(string);  }  Map<String, List<String>> theMap = computeAdjacentWords_01(list);  printHighChangeables(theMap);  System.out.println('\n' + "----------------------------");  Map<String, List<String>> theMap2 = computeAdjacentWords_02(list);  printHighChangeables(theMap2);  System.out.println('\n' + "----------------------------");  Map<String, List<String>> theMap3 = computeAdjacentWords_03(list);  printHighChangeables(theMap3);}}
原创粉丝点击