java中的自动排序集合 ---- 20160809
程序员文章站
2022-04-17 09:06:20
...
TreeSet的实现:
http://blog.csdn.net/hudashi/article/details/6943522
TreeMap实现:
http://blog.csdn.net/hudashi/article/details/6944059
需要注意:
1. 当利用comparator比较两个元素相等时,插入的时候会失败。而hashset是发现两个元素相等(即:两个元素的hashcode相同,equals方法比较之后也相等)时,插入失败返回false。这说明可能treeset并不是真正的set,因为即使两个元素的hashcode相同,equals方法比较之后也相等,但是如果comparator返回两个对象不相等,也是可以插入的,而hashset插入事则会失败。
2. 排序只在插入时发生,如果后面你修改了元素的数据,元素的位置不会变。
测试类:
ChineseCharCount, 保存一个字符和它出现的次数。本来想测试读取一个文件中的所有中文字符,然后得到出现最多的字符以及出现了多少次的。本想用treeset进行排序,但是发现不行,最后还是直接用的ArrayList,然后用Collections的sort
(Comparator comparator)方法完成的。
package _00_ReadAndCountChineseCharacters; public class ChineseCharCount { char ch; int count; public ChineseCharCount(char ch, int count) { // TODO Auto-generated constructor stub this.ch = ch; this.count = count; } public char getCh() { return ch; } public void setCh(char ch) { this.ch = ch; } public void setCount(int count) { this.count = count; } public String toString() { return ch + ":appeared " + count + " times"; } public int getCount() { return count; } @Override public boolean equals(Object obj) { // TODO Auto-generated method stub if (obj == null) { return false; } if (obj == this) { return true; } if (!(obj instanceof ChineseCharCount)) { return false; } ChineseCharCount te = (ChineseCharCount) obj; if (te.ch == this.ch) { return true; } return false; } @Override public int hashCode() { // TODO Auto-generated method stub return (ch + "").hashCode(); } }
ChineseCharComparator,直接通过比较count来对比大小。
package _00_ReadAndCountChineseCharacters; import java.util.Comparator; public class ChineseCharComparator implements Comparator<ChineseCharCount>{ public int compare(ChineseCharCount o1, ChineseCharCount o2) { // TODO Auto-generated method stub if(o1 == o2) return 0; if(o1!=null&&o2==null) return -1; else if(o1==null&&o2!=null) return 1; if (o1.count < o2.count) return 1; else if (o1.count > o2.count) return -1; else return 0; } }
ReadAndCountChineseCharacters,测试类。直接读取文件,count,然后排序,输出前三。
package _00_ReadAndCountChineseCharacters; import java.io.FileReader; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.TreeSet; public class ReadAndCountChineseCharacters { public static void main(String[] args) throws Exception { String classPath = ReadAndCountChineseCharacters.class.getResource("").getPath(); System.out.println(classPath); String filePath = classPath + "ChineseSentence.txt"; // InputStream in = new FileInputStream(filePath); List<ChineseCharCount> chList = new ArrayList<ChineseCharCount>(); FileReader fr = new FileReader(filePath); int i; while ((i = fr.read()) != -1) { char next = (char) i; if(next == '\n' || next == '\t') continue; boolean hasCh = false; for (ChineseCharCount chCount : chList) { if (next == chCount.ch) { hasCh = true; chCount.count = chCount.count + 1; break; } } if (!hasCh) { chList.add(new ChineseCharCount(next, 1)); } } fr.close(); ChineseCharComparator comparator = new ChineseCharComparator(); Collections.sort(chList, comparator); for (int j = 0; j < 3; j++) { System.out.println(chList.get(j)); } } }
TestTreeSet 编写排序时,遇到的问题,通过下面的测试类进行了总结:
package _00_ReadAndCountChineseCharacters; import java.util.HashMap; import java.util.HashSet; import java.util.TreeSet; public class TestTreeSet { public static void main(String[] args) { ChineseCharCount ch = new ChineseCharCount('a', 1); ChineseCharCount ch2 = new ChineseCharCount('a', 2); ChineseCharCount ch3 = new ChineseCharCount('a', 1); ChineseCharCount ch4 = new ChineseCharCount('c', 1); ChineseCharComparator comparator = new ChineseCharComparator(); TreeSet<ChineseCharCount> treeSet = new TreeSet<>(comparator); HashSet<ChineseCharCount> hashSet = new HashSet<>(); HashMap<String, String> haspMap = new HashMap<>(); /* * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old value is replaced. * * the previous value associated with key, or null if there was no mapping for key. * (A null return can also indicate that the map previously associated null with key.) */ haspMap.put("1", "1"); System.out.println("abc123".hashCode()); System.out.println("".hashCode()); System.out.println(new String("abc123").hashCode()); System.out.println(new String("").hashCode()); /* * Adds the specified element to this set if it is not already present. * More formally, adds the specified element e to this set if the set * contains no element e2 such that (e==null ? e2==null : e.equals(e2)). * If this set already contains the element, the call leaves the set unchanged and returns false. */ System.out.println("add into treeset"); System.out.println(treeSet.add(ch)); System.out.println(treeSet.add(ch2)); System.out.println(treeSet.add(ch3)); System.out.println(treeSet.add(ch4)); /* * Adds the specified element to this set if it is not already present. * More formally, adds the specified element e to this set if this set * contains no element e2 such that (e==null ? e2==null : e.equals(e2)). * If this set already contains the element, the call leaves the set unchanged and returns false. */ System.out.println("add into hashSet"); System.out.println(hashSet.add(ch)); System.out.println(hashSet.add(ch2)); System.out.println(hashSet.add(ch3)); System.out.println(hashSet.add(ch4)); System.out.println("From the test result we can see, " + "treeset is not really a set. AS it allowed duplicate " + "attribute(determinter by hashCode and equals method). " + "Instead, it didn't allwed two attributes wihich is " + "equals to each other(determined by the comparator)."); /* * 从测试结果可以看出,如果两个元素利用comparator进行比较是相等的插入会失败。 */ for(ChineseCharCount chs : treeSet) System.out.println(chs); treeSet.first().count = 0; treeSet.last().count = 2; System.out.println(treeSet.add(ch3)); /* * 从测试结果可以看出,treeset只会在存入set的时候进行排序, * 当做了更改时不会重新排序。 */ for(ChineseCharCount chs : treeSet) System.out.println(chs); } }