第07章 集合
1 /***************** 2 ***第七章 集合 3 *******知识点: 4 **************1.Collection和Iterator接口 5 ******************1.1 Collection接口简介 6 ******************1.2 Iterator接口简介 7 ******************1.3 Map接口简介 8 **************2.Set接口 9 ******************2.1 HashSet类 10 ******************2.2 TreeSet类 11 ******************2.3 EnumSet类 12 **************3.List接口 13 ******************3.1 ArrayList类 14 ******************3.2 LinkedList类 15 ******************3.3 Vector类 16 ******************3.4 Stack类 17 **************4.Queue接口 18 ******************4.1 PriorityQueue类 19 **************5.Map接口 20 ******************5.1 HashMap类 21 ******************5.2 Hashtable类 22 ******************5.3 SortedMap接口 23 ******************5.4 TreeMap类 24 ******************5.5 WeakHashMap类 25 ******************5.6 IdentityHashMap类 26 ******************5.7 EnumMap类 27 **************6.集合操作工具类 28 ******************6.1 排序操作 29 ******************6.2 查找,替换操作 30 ******************6.3 同步控制 31 ******************6.4 总结 32 */ 33 import java.util.*; 34 35 /* 36 * 演示需用类 37 */ 38 class Person implements Comparable{ 39 private int id; 40 private String name; 41 Person(){ 42 this.id = 0; 43 this.name = "无名氏"; 44 } 45 46 Person(int id, String name){ 47 this.id = id; 48 this.name = name; 49 } 50 51 public String toString(){ 52 return "id:" + id + ",name:" +name; 53 } 54 55 //重写接口中的方法 用于比较 56 public int compareTo(Object o){ 57 Person p = (Person) o; 58 int result = id < p.id ? 1 : (id == p.id ? 0 : -1); //降序 59 //int result = id > p.id ? 1 : (id == p.id ? 0 : -1); //降序 60 if(result == 0){ 61 result = name.compareTo(p.name);//注意区别:这里调用String的compareTo方法 62 } 63 return result; 64 } 65 } 66 67 /* 68 * 演示枚举类 69 */ 70 enum MyEnum{ 71 BLACK,WIHTE,RED,BLUE,GREEN 72 } 73 74 public class test7{ 75 public static void main(String[] args){ 76 showDemo("1.Collection和Iterator接口"); 77 demoCollectionAndIterator(); //1.Collection和Iterator接口 78 79 showDemo("2.Set接口"); 80 demoSet(); //2.Set接口 81 82 showDemo("3.List接口"); 83 demoList(); //3.List接口 84 85 showDemo("4.Queue接口"); 86 demoQueue(); //4.Queue接口 87 88 showDemo("5.Map接口"); 89 demoMap(); //5.Map接口 90 91 showDemo("6.集合操作工具类"); 92 demoTools(); //6.集合操作工具类 93 } 94 95 /**1.Collection和Iterator接口**/ 96 public static void demoCollectionAndIterator(){ 97 /**1.1 Collection接口简介**/ 98 //Collection接口是集合父接口之一 实现子接口有 Set接口、List接口 99 //其中Set接口:不能包含重复的元素 100 //List接口:一个有序的集合 101 102 /**1.2 Iterator接口简介**/ 103 //Iterator接口是迭代器 104 //用于遍历集合中的元素 105 106 /**1.3 Map接口简介**/ 107 //Map接口是集合父接口之一 实现子类有SortMap、HashMap 108 //包含了key-value 俗称键值对 其中 key不能重复 109 } 110 111 /**2.Set接口**/ 112 public static void demoSet(){ 113 //Set接口:不能包含重复的元素、允许包含值为null的元素但只能有一个 114 115 /**2.1 HashSet类**/ 116 //HashSet类按照哈希算法来存取集合中的对象,存取速度比较快 117 System.out.println("演示HashSet类======="); 118 HashSet h_HashSet = new HashSet(); 119 Person p1 = new Person(); 120 h_HashSet.add("1");//字符串 121 h_HashSet.add('2');//字符 122 h_HashSet.add(3);//整型 123 h_HashSet.add(true);//布尔型 124 h_HashSet.add(1.0); 125 h_HashSet.add(new Integer(3));//不会被添加 因为重复了 126 h_HashSet.add(p1);//对象 127 System.out.println("集合长度为:" + h_HashSet.size());//获取集合长度 128 129 Iterator i_Iterator = h_HashSet.iterator();//得到遍历的迭代器 130 while(i_Iterator.hasNext()){ 131 Object o = (Object)(i_Iterator.next());//通过迭代器返回元素 注意返回为Object类型 132 System.out.println("集合元素:" + o);//需注意如果是自定义的类型 需要重写toString方法 133 } 134 135 System.out.println("判断集合是否为空:" + h_HashSet.isEmpty());//判断集合是否为空 136 h_HashSet.remove(3);//删除元素 137 h_HashSet.remove((float)1.0);//不能删除元素 类型不匹配 138 139 System.out.println("集合长度为:" + h_HashSet.size());//获取集合长度 140 i_Iterator = h_HashSet.iterator(); 141 while(i_Iterator.hasNext()){ 142 Object o = (Object)(i_Iterator.next());//通过迭代器返回元素 注意返回为Object类型 143 System.out.println("集合元素:" + o); 144 } 145 146 System.out.println(h_HashSet);//将集合打印出来 147 148 /**2.2 TreeSet类**/ 149 //TreeSet类是一个有序集合,元素将按照升序排列,缺省是按照自然排序进行排列。 150 //所以该集合中的元素要实现Comparable接口或者有一个自定义的比较器 151 //另外集合中的元素存储顺序跟加入的顺序无关 152 System.out.println("演示TreeSet类======="); 153 TreeSet t_TreeSet1 = new TreeSet(); 154 t_TreeSet1.add("aaaa"); 155 t_TreeSet1.add("ccc"); 156 t_TreeSet1.add("ac"); 157 t_TreeSet1.add("bc"); 158 Iterator i_Iterator_TreeSet = t_TreeSet1.iterator(); 159 while(i_Iterator_TreeSet.hasNext()){ 160 Object o = i_Iterator_TreeSet.next(); 161 System.out.println("集合对象:" + o);//注意输出结果跟加入顺利对比 发现无关 162 } 163 164 System.out.println("集合中第一个对象:" + (Object)t_TreeSet1.first());//返回第一个元素 165 System.out.println("集合中第一个对象:" + (Object)t_TreeSet1.last());//返回最后一个元素 166 167 System.out.println("返回不小于acd的集合对象:" + (Object)t_TreeSet1.ceiling("acd")); 168 //返回一个不小于acd的集合元素(非随机 就是一个且最接近的一个) 169 170 Person p1_TreeSet = new Person(); 171 Person p2_TreeSet = new Person(0,"aaa"); 172 Person p3_TreeSet = new Person(1,"aaa"); 173 174 TreeSet t_TreeSet2 = new TreeSet(); 175 t_TreeSet2.add(p1_TreeSet); 176 t_TreeSet2.add(p2_TreeSet); 177 t_TreeSet2.add(p3_TreeSet); 178 179 System.out.println("集合中所有对象:" + t_TreeSet2); 180 181 182 /**2.3 EnumSet类**/ 183 //这个类是1.5开始有的 184 //目前个人使用量几乎为零,很少使用 185 //其使用方式和普通的Set没有区别,只是构造方法有一些特殊的而已 186 //多种添加集合元素方式 187 System.out.println("演示EnumSet类======="); 188 189 //第一种创建一个指定类型的空集合 然后再添加元素 190 EnumSet<MyEnum> e_EnumSet1 = EnumSet.noneOf(MyEnum.class); 191 e_EnumSet1.add(MyEnum.BLACK); 192 e_EnumSet1.add(MyEnum.RED); 193 e_EnumSet1.add(MyEnum.BLUE); 194 System.out.println("e_EnumSet集合中的对象:" + e_EnumSet1); 195 196 //第二种创建一个指定类型的所有数据集合 197 EnumSet<MyEnum> e_EnumSet2 = EnumSet.allOf(MyEnum.class); 198 System.out.println("e_EnumSet集合中的对象:" + e_EnumSet2); 199 200 //第三种创建一个指定类型的指定初始化数据的集合 201 EnumSet<MyEnum> e_EnumSet3 = EnumSet.of(MyEnum.WIHTE,MyEnum.GREEN); 202 System.out.println("e_EnumSet集合中的对象:" + e_EnumSet3); 203 204 //第四种创建一个指定类型的指定数据范围的集合 205 EnumSet<MyEnum> e_EnumSet4 = EnumSet.range(MyEnum.WIHTE,MyEnum.BLUE);//从WIHTE到BLUE 的所有元素 206 System.out.println("e_EnumSet集合中的对象:" + e_EnumSet4); 207 208 209 //总结: 210 // 1.HashSet 速度快 且使用居多 211 // 2.TreeSet 自动实现排序(需要为元素实现比较器) 212 // 3.EnumSet 枚举 然并卵 213 // 最后对时间效率有要求使用 HashSet 对排序有要求使用 TreeSet EnumSet(忘了它吧) 214 } 215 216 /**3.List接口**/ 217 public static void demoList(){ 218 //List接口:一个有序的集合 对插入的顺序有序 219 220 /**3.1 ArrayList类**/ 221 //1.基于数组实现的List类 222 //2.查找和定位操作快 223 //3.添加和删除操作慢 224 //4.线程不安全 225 System.out.println("演示ArrayList类======="); 226 ArrayList a_ArrayList = new ArrayList();//默认10个长度 后面可以动态加载 227 for(int i = 0; i < 10; i++){ 228 a_ArrayList.add(i); //加载元素 229 } 230 231 //使用foreach遍历集合 232 for(Object j :a_ArrayList){ 233 System.out.println("元素:" + j); 234 } 235 236 //使用get方法遍历 237 for(int i= 0 ;i < 10 ; i++){ 238 System.out.println("元素:" + a_ArrayList.get(i)); 239 } 240 //推荐使用后者遍历 241 System.out.println(a_ArrayList);//将所有元素打印出来 242 //更多方法使用详见API 243 244 245 /**3.2 LinkedList类**/ 246 //1.基于链表实现的List类 247 //2.查找和定位操作慢 248 //3.添加和删除操作快 249 //4.线程不安全 250 //使用跟ArrayList相似 具体使用时查看API即可 需注意实现的方式采用的是链表 251 System.out.println("演示LinkedList类======="); 252 253 /**3.3 Vector类**/ 254 //1.基于数组实现的List类 255 //2.线程安全 256 //3.已经被ArrayList类取代得差不多了 257 //使用跟ArrayList相似 具体使用时查看API即可 一般不会使用 毕竟ArrayList几乎可以取代它了无论是从执行效率还是功能上 258 System.out.println("演示Vector类======="); 259 260 /**3.3 Stack类**/ 261 //1.Vector类的子类 262 //2.实现模拟栈操作 263 System.out.println("演示Stack类======="); 264 Stack s_Stack = new Stack(); 265 System.out.println("是否为空栈:" + s_Stack.isEmpty()); 266 for(int i = 0 ;i < 10; i++){ 267 s_Stack.push("元素" + i);//入栈 268 } 269 System.out.println("栈元素有:" + s_Stack); 270 String str_Stack = "元素3"; 271 System.out.println("元素3在第:" + (s_Stack.search((Object) str_Stack)) + "位上");//返回在堆栈中的位置 以1开始 272 273 System.out.println("栈顶元素是:" + s_Stack.peek()); 274 275 //删除前先判断是否为空栈 276 if(!s_Stack.isEmpty()){ 277 System.out.println("移除栈顶元素是:" + s_Stack.pop()); 278 } 279 System.out.println("栈元素有:" + s_Stack); 280 281 //总结: 282 //1.如果需要遍历List集合元素,对应ArrayList、Vector集合,则应该使用随机访问方法(get)来遍历集合元素, 283 // 这样性能更好。对应LinkedList集合,则应采用迭代器(Iterator)来遍历集合元素。 284 //2.如果需要经常执行插入、删除操作来改变集合大小,则应该使用LinkedList集合,而不是ArrayList 285 //3.如果需要查询和定位操作比较频繁时,则应该使用ArrayList集合,而不是LinkedList 286 //4.如果多条线程需要同时访问List集合中的元素,可以考虑使用Vector这个同步实现。 287 // 或者使用ArrayList然后再手动设置加锁(推荐后者) 288 } 289 290 /**4.Queue接口**/ 291 public static void demoQueue(){ 292 //Queue接口:优先队列集合 293 //本质上就是一个最小堆 294 //很少用到 了解即可 295 296 /**4.1 PriorityQueue类**/ 297 } 298 299 /**5.Map接口**/ 300 public static void demoMap(){ 301 //Map接口:实现键值对的接口 302 303 /**5.1 HashMap类**/ 304 System.out.println("演示HashMap类======="); 305 //不同步,故线程不安全 306 //一键值 (键不同时,值可以相同 但键不能相同 可以为null) 307 // 初始化随机种子 308 Random r = new Random(); 309 // 新建HashMap 310 HashMap map_HashMap = new HashMap(); 311 // 添加操作 312 map_HashMap.put("one", r.nextInt(10)); 313 map_HashMap.put("two", r.nextInt(10)); 314 map_HashMap.put("two", r.nextInt(10));//不会被添加因为存在该键了 315 map_HashMap.put(null, null);//可以为空 316 map_HashMap.put("two1", r.nextInt(10)); 317 map_HashMap.put("three", r.nextInt(10)); 318 // 打印出map 319 System.out.println("map_HashMap:"+map_HashMap ); 320 321 // 通过entrySet-Iterator遍历key-value 322 System.out.println("通过entrySet-Iterator遍历key-value"); 323 Iterator iter_HashMap1 = map_HashMap.entrySet().iterator(); 324 while(iter_HashMap1.hasNext()) { 325 Map.Entry entry = (Map.Entry)iter_HashMap1.next(); 326 System.out.println("next : "+ entry.getKey() +" - "+entry.getValue()); 327 } 328 329 //通过keyset - Iterator遍历key-value 330 System.out.println("通过keyset - Iterator遍历key-value"); 331 Iterator iter_HashMap2 = map_HashMap.keySet().iterator(); 332 while (iter_HashMap2.hasNext()){ 333 Object key = iter_HashMap2.next(); 334 Object val = map_HashMap.get(key); 335 System.out.println("next : "+ key +" - "+ val); 336 } 337 // HashMap的键值对个数 338 System.out.println("size:"+map_HashMap.size()); 339 // containsKey(Object key) :是否包含键key 340 System.out.println("contains key two : "+map_HashMap.containsKey("two")); 341 System.out.println("contains key five : "+map_HashMap.containsKey("five")); 342 // containsValue(Object value) :是否包含值value 343 System.out.println("contains value 0 : "+map_HashMap.containsValue(new Integer(0))); 344 // remove(Object key) : 删除键key对应的键值对 345 map_HashMap.remove("three"); 346 System.out.println("map:"+map_HashMap ); 347 // clear() : 清空HashMap 348 map_HashMap.clear(); 349 // isEmpty() : HashMap是否为空 350 System.out.println((map_HashMap.isEmpty()?"map_HashMap is empty":"map_HashMap is not empty") ); 351 352 353 //两种遍历方式 推荐entrySet-Iterator这种方法 效率要高点 354 //对于keySet其实是遍历了2次,一次是转为iterator,一次就从hashmap中取出key所对于的value。 355 //而entryset只是遍历了1次,他把key和value都放到了entry中,所以就快了。 356 357 /**5.2 Hashtable类**/ 358 //用法跟HashMap 差不多 359 //区别: 360 //1.Hashtable 是同步的 即线程安全 在多线程下可以直接使用 而HashMap则要手动设置同步 361 //2.Hashtable 不管key 或者value 均不允许出现null 362 //3.继承不同 Hashtable ——Dictionary 而HashMap——AbstractMap 363 //4.初始化大小和扩容方式不同 364 //5.历史遗留问题导致Hashtable 还使用Enumeration方式遍历元素 365 //最后推荐使用HashMap 366 367 /**5.3 SortedMap接口**/ 368 // 保证按照键的升序排列的映射,可以按照键的自然顺序(参见 Comparable 接口)进行排序, 369 //或者通过创建有序映射时提供的比较器进行排序 370 //所以所有的键必须是可以比较的 371 372 /**5.4 TreeMap类**/ 373 //TreeMap是SortedMap接口的基于红黑树的实现 374 //此类保证了映射按照升序顺序排列关键字, 根据使用的构造方法不同,可能会按照键的类的自然顺序进行排序 375 //注意1:此实现不是同步的。不是线程安全的。 376 //注意2:TreeMap是用键来进行升序顺序来排序的。通过Comparable 或 Comparator来排序。 377 //注意3:由所有此类的“collection 视图方法”所返回的迭代器都是快速失败的。 378 //注意4:和HashMap一样,如果插入重复的元素,后面的元素会覆盖前面的。 379 //注意5: 键不可以为null,但是值可以为null 380 System.out.println("演示TreeMap类======="); 381 Random r_TreeMap = new Random(); 382 TreeMap t_TreeMap = new TreeMap(); 383 Person p_TreeMap1 = new Person(); 384 Person p_TreeMap2 = new Person(1,"aaaa"); 385 Person p_TreeMap3 = new Person(2,"aaaa"); 386 Person p_TreeMap4 = new Person(0,"aaaa"); 387 t_TreeMap.put(r_TreeMap.nextInt(10),p_TreeMap1); 388 t_TreeMap.put(r_TreeMap.nextInt(10),p_TreeMap2); 389 t_TreeMap.put(r_TreeMap.nextInt(10),p_TreeMap3); 390 t_TreeMap.put(r_TreeMap.nextInt(10),p_TreeMap4); 391 t_TreeMap.put(r_TreeMap.nextInt(10),null); //键不可以为null 值可以 392 System.out.println("集合中元素有:" + t_TreeMap); 393 394 for(Object o:t_TreeMap.values()){ 395 System.out.println("元素值:" + o); 396 } 397 //判断是否存在键 398 System.out.println("是否包含键值为3的键:" + t_TreeMap.containsKey(new Integer(3))); 399 400 //判断是否存在值 401 System.out.println("是否包含p_TreeMap1对象:" + t_TreeMap.containsValue((Object)p_TreeMap1));//是否存在p_TreeMap1 402 System.out.println("是否包含:" + t_TreeMap.containsValue(new Person()));//重新new对象跟原有对象不一样 403 404 //判断是否存在值 405 System.out.println("是否包含new Person(4,1111)对象:" + t_TreeMap.containsValue(new Person(4,"1111"))); 406 407 408 /**5.5 WeakHashMap类**/ 409 //WeakHashMap是一种改进的HashMap,它对key实行“弱引用”, 410 //如果一个key不再被外部所引用,那么该key可以被GC回收。 411 //一般很少用到 412 //用法想见API 跟HashMap用法差不多 413 414 /**5.6 IdentityHashMap类**/ 415 // IdentityHashMap类是一种允许key 的内容可以重复的集合类 416 //一般很少用到 417 //用法想见API 跟HashMap用法差不多 418 419 /**5.7 EnumMap类**/ 420 //1. 使用EnumMap时,必须指定枚举类型。 421 //2. key不能为null 422 //3. EnumMap内部以数组实现,性能更好。 423 System.out.println("演示EnumMap类======="); 424 EnumMap e_EnumMap = new EnumMap(MyEnum.class); 425 e_EnumMap.put(MyEnum.BLACK,"黑色"); 426 e_EnumMap.put(MyEnum.WIHTE,"白色"); 427 e_EnumMap.put(MyEnum.RED,"红色"); 428 System.out.println("集合对象有:" + e_EnumMap); 429 Iterator i_EnumMap = e_EnumMap.entrySet().iterator(); 430 while(i_EnumMap.hasNext()){ 431 Map.Entry entry_EnumMap = (Map.Entry)i_EnumMap.next(); 432 System.out.println("对象——key:" + entry_EnumMap.getKey()+ ",value:"+entry_EnumMap.getValue()); 433 } 434 435 } 436 437 /**6.集合操作工具类**/ 438 public static void demoTools(){ 439 //Collections类是一个集合操作工具类 440 /**6.1 排序操作**/ 441 Person p_Collections1 = new Person(1,"黄"); 442 Person p_Collections3 = new Person(3,"李"); 443 Person p_Collections2 = new Person(2,"赵"); 444 Person p_Collections4 = new Person(4,"钱"); 445 List l_Array = new ArrayList(); 446 l_Array.add(p_Collections1); 447 l_Array.add(p_Collections2); 448 l_Array.add(p_Collections3); 449 l_Array.add(p_Collections4); 450 451 System.out.println("集合对象:" + l_Array); 452 //排序(升序) 453 Collections.sort(l_Array); 454 System.out.println("排序后,集合对象:" + l_Array); 455 456 //反转(执行排序后再执行反转 相当于降序) 457 Collections.reverse(l_Array); 458 System.out.println("反转后,集合对象:" + l_Array); 459 460 461 //混乱排序 462 Collections.shuffle(l_Array);//每次结果可能不一样 463 System.out.println("混乱排序后,集合对象:" + l_Array); 464 465 /**6.2 查找,替换操作**/ 466 //查找 指定元素查找 返回索引 467 System.out.println("查找str_Collections元素的位置:" + Collections.binarySearch(l_Array,p_Collections1,null)); 468 469 //交换 指定位置交换 470 System.out.println("交换前集合对象:" + l_Array); 471 Collections.swap(l_Array,1,2); 472 System.out.println("交换后集合对象:" + l_Array); 473 474 //替换 指定元素替换 475 Person p_Collections5 = new Person(5,"王"); 476 System.out.println("替换前集合对象:" + l_Array); 477 Collections.replaceAll(l_Array,p_Collections4,p_Collections5); 478 System.out.println("替换后集合对象:" + l_Array); 479 480 /**6.3 同步控制**/ 481 //使用该工具类的同步方法返回可同步的集合对象 482 Collection c=Collections.synchronizedCollection(new ArrayList()); 483 List l=Collections.synchronizedList(new ArrayList()); 484 Set s=Collections.synchronizedSet(new HashSet()); 485 Map m=Collections.synchronizedMap(new HashMap()); 486 487 /**6.4 总结**/ 488 //1.Set类 489 //1.1 如果希望按照元素插入集合的顺序进行提取元素,用LinkedHashSet,它的元素按添加的顺序存储 490 //1.2 一般使用HashSet,因为它的效率比LinkedHashSet高 491 //1.3 TreeSet(集合元素有排序关系) 492 //2.List类 493 //2.1 ArrayList使用数组实现的动态扩展容量的list 定位查找操作效率快,不同步 494 //2.2 LinkedList链式实现的list,增加修改效率快,不同步 495 //2.3 Vector 同步版的ArrayList,因为同步,故效率不如ArrayList 496 //2.4 Stack继承Vector,模拟实现栈 497 //3.Map类 498 //3.1 键值对同List和Set不同 499 //3.2 HashMap:效率高 500 //3.3 TreeMap:排序性 501 //4.Collections类 502 //4.1 提供了许多静态的方法来管理集合 503 //5.Arrays类 504 //5.1 提供了对数组排序,查找,比较,填充元素的各种静态方法。 505 506 } 507 508 509 /* 510 * 抽取打印演示函数 用于打印演示功能提示 511 */ 512 public static void showDemo(String demoStr){ 513 System.out.println("演示:" + demoStr); 514 } 515 516 }