框架图
集合类
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
数组和集合类同是容器,有何不同?
数组存储同一类型的基本数据类型和对象;集合可以存储不同类型的对象。数组的长度是固定的;集合的长度是可变的。
总结集合类的特点:集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
collection接口
Collection定义了集合框架的共性功能。
1,添加
add(e);
addAll(collection);
2,删除
remove(e);
removeAll(collection);
clear();
3,判断。
contains(e);
isEmpty();
4,获取
iterator();
size();
5,获取交集。
retainAll();
6,集合变数组。
toArray();
1 import java.util.*; 2 class CollectionDemo 3 { 4 public static void main(String[] args) 5 { 6 base_method(); 7 method_2(); 8 } 9 public static void method_2() 10 { 11 ArrayList al1 = new ArrayList(); 12 13 al1.add("java01"); 14 al1.add("java02"); 15 al1.add("java03"); 16 al1.add("java04"); 17 18 ArrayList al2 = new ArrayList(); 19 20 al2.add("java01"); 21 al2.add("java02"); 22 al2.add("java07"); 23 al2.add("java08"); 24 26 al1.retainAll(al2);//5,取交集,无交集为空 27 sop(al1); 28 sop(al2); 31 } 33 public static void base_method() 34 { 35 //创建一个集合容器。使用Collection接口的子类。ArrayList 36 ArrayList al = new ArrayList(); 37 38 //1,添加元素。 39 al.add("java01");//add(Object obj); 40 al.add("java02"); 41 al.add("java03"); 42 al.add("java04"); 43 44 //打印原集合。 45 sop("原集合:"+al); 46 48 //3,删除元素。 49 al.remove("java03"); 50 al.clear();//清空集合。 51 53 //4,判断元素。 54 sop("java03是否存在:"+al.contains("java03")); 55 sop("集合是否为空?"+al.isEmpty()); 56 58 //2,获取个数。集合长度。 59 sop("集合长度:"+al.size()); 60 61 //打印改变后的集合。 62 sop(al); 63 64 } 65 public static void sop(Object obj) 66 { 67 System.out.println(obj); 68 } 69 }
Iterator接口
Iterator接口可以建立引用,指向子类的对象;这个对象不是通过new建立的,而是通过iterator方法建立的。
Iterator it = arr.iterator();获取迭代器,用于取出集合中的元素。迭代器是取出方式,会直接访问集合中的元素,所以将迭代器通过内部类的形式来进行描述,通过容器的iterator()方法获取该内部类的对象。
如何获取集合的对象?每个集合都通过对外提供的一个方法,iteretor()。接口提供引用,集合提供对象,配合在一起使用,降低了使用者和取出动作的耦合性。例如,夹娃娃的机器。
1 //1,代码阅读性好。 2 Iterator it = arr.iterator(); 3 4 while(it.hasNext()) 5 { 6 System.out.println(it.next()); 7 } 8 //2,常用写法,将it作为局部变量,节省内存资源。 9 for(Iterator it = arr.iterator();it.hasNext(); ) 10 { 11 System.out.println(it.next()); 12 }
注意:
迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)。
迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。
迭代器的next方法返回值类型是Object,所以要记得类型转换。
List接口
Collection接口有两个子接口:
List(列表),Set(集)
List:可存放重复元素,元素存取是有序的。
Set:不可以存放重复元素,元素存取是无序的。
List
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。
List:
特有方法。凡是可以操作角标的方法都是该体系特有的方法。
增
add(index,element);
addAll(index,Collection);
删
remove(index);
改
set(index,element);
查
get(index):
subList(from,to);
listIterator();
int indexOf(obj):获取指定元素的位置。
ListIterator listIterator();
1 import java.util.*; 2 class ListDemo 3 { 4 public static void sop(Object obj) 5 { 6 System.out.println(obj); 7 } 8 public static void main(String[] args) 9 { 10 ArrayList al = new ArrayList(); 11 12 //添加元素 13 al.add("java01"); 14 al.add("java02"); 15 al.add("java03"); 16 17 sop("原集合是:"+al); 18 //在指定位置添加元素。 19 al.add(1,"java09"); 20 21 //删除指定位置的元素。 22 //al.remove(2); 23 24 //修改元素。 25 //al.set(2,"java007"); 26 27 //通过角标获取元素。 28 sop("get(1):"+al.get(1)); 29 sop(al); 30 31 //for循环获取所有元素。 32 for(int x=0; x<al.size(); x++) 33 { 34 System.out.println("al("+x+")="+al.get(x)); 35 } 36 //迭代器获取所有元素 37 Iterator it = al.iterator(); 38 while(it.hasNext()) 39 { 40 sop("next:"+it.next()); 41 } 42 43 //通过indexOf获取对象的位置。 44 sop("index="+al.indexOf("java02")); 45 List sub = al.subList(1,3);//获取子列表 46 sop("sub="+sub); 47 } 48 }
在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException并发修改异常。所以,在迭代器时,只能用迭代器的方法操作元素,但是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。该接口只能通过List集合的listIterator方法获取。
1 import java.util.*; 2 class ListDemo 3 { 4 public static void sop(Object obj) 5 { 6 System.out.println(obj); 7 } 8 9 public static void main(String[] args) 10 { 11 ArrayList al = new ArrayList(); 12 13 al.add("java01"); 14 al.add("java02"); 15 al.add("java03"); 16 17 sop(al); 18 19 ListIterator li = al.listIterator(); 20 21 sop("hasPrevious():"+li.hasPrevious()); 22 23 while(li.hasNext()) 24 { 25 Object obj = li.next(); 26 27 if(obj.equals("java02")) 28 //li.add("java009"); 29 li.set("java006"); 32 } 33 sop("hasNext():"+li.hasNext()); 34 sop("hasPrevious():"+li.hasPrevious()); 35 while(li.hasPrevious())//逆向遍历 36 { 37 sop("pre::"+li.previous()); 38 } 39 40 sop(al); 41 } 42 } 43 ---------- java ---------- 44 [java01, java02, java03] 45 hasPrevious():false 46 hasNext():false 47 hasPrevious():true 48 pre::java03 49 pre::java006 50 pre::java01 51 [java01, java006, java03] 52 53 输出完成 (耗时 0 秒) - 正常终止
LinkedList特有方法
1 import java.util.*; 2 /* 3 LinkedList:特有方法: 4 addFirst(); 5 addLast(); 6 7 getFirst(); 8 getLast(); 9 获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException 10 11 removeFirst(); 12 removeLast(); 13 获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException 14 15 16 在JDK1.6出现了替代方法。 17 offerFirst(); 18 offerLast(); 19 20 peekFirst(); 21 peekLast(); 22 获取元素,但不删除元素。如果集合中没有元素,会返回null。 23 24 pollFirst(); 25 pollLast(); 26 获取元素,但是元素被删除。如果集合中没有元素,会返回null。 27 */ 29 class LinkedListDemo 30 { 31 public static void main(String[] args) 32 { 33 LinkedList link = new LinkedList(); 34 35 link.offerFirst("java01"); 36 link.offerFirst("java02"); 37 link.offerFirst("java03"); 38 link.offerFirst("java04"); 39 40 sop(link); 41 sop(link.peekFirst()); 42 sop(link.peekLast()); 43 //sop(link.removeFirst()); 44 //sop(link.removeFirst()); 45 46 sop("size="+link.size()); 47 48 while(!link.isEmpty()) 49 { 50 sop(link.pollLast()); 51 } 52 sop("size="+link.size()); 53 } 54 55 public static void sop(Object obj) 56 { 57 System.out.println(obj); 58 } 59 }
ArrayList练习。将自定义对象作为元素存到ArrayList集合中,并去除重复元素。
由于数据结构不同,某些方法依赖的底层方法也不同,ArrayList和LinkedList中的contains、remove依赖的都是底层的equals方法。默认的equals方法依据对象的内存地址值来比较对象是否相同,可以根据对象的属性自定义equals方法。
1 import java.util.*; 2 /* 3 将自定义对象作为元素存到ArrayList集合中,并去除重复元素。 4 比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。 5 思路: 6 1,对人描述,将数据封装进人对象。 7 2,定义容器,将人存入。 8 3,取出。 9 List集合判断元素是否相同,依据是元素的equals方法。 10 */ 11 class Person 12 { 13 private String name; 14 private int age; 15 Person(String name,int age) 16 { 17 this.name = name; 18 this.age = age; 19 } 20 21 public boolean equals(Object obj)//复写equals方法 22 { 23 24 if(!(obj instanceof Person))//判断是否属于该类对象 25 return false; 26 27 Person p = (Person)obj; 28 System.out.println(this.name+"和"+p.name+"比一下"); 29 30 return this.name.equals(p.name) && this.age == p.age; 31 } 32 public String getName() 33 { 34 return name; 35 } 36 public int getAge() 37 { 38 return age; 39 } 40 } 41 class ArrayListTest 42 { 43 public static void sop(Object obj) 44 { 45 System.out.println(obj); 46 } 47 public static void main(String[] args) 48 { 49 ArrayList al = new ArrayList(); 50 51 al.add(new Person("lisi01",30));//al.add(Object obj);//Object obj = new Person("lisi01",30); 52 al.add(new Person("lisi02",32)); 53 al.add(new Person("lisi02",32)); 54 al.add(new Person("lisi03",33)); 55 al.add(new Person("lisi04",35)); 56 57 al = singleElement(al); 58 59 //sop("remove 03 :"+al.remove(new Person("lisi03",33)));//remove方法底层也是依赖于元素的equals方法。 60 61 Iterator it = al.iterator(); 62 while(it.hasNext()) 63 { //Object obj=it。next(); 64 //Person p = (Person)obj; 65 Person p = (Person)it.next();//多态调用子类特有方法向下转型 66 sop(p.getName()+"::"+p.getAge()); 67 } 68 } 69 public static ArrayList singleElement(ArrayList al) 70 { 71 //定义一个临时容器。 72 ArrayList newAl = new ArrayList(); 73 74 Iterator it = al.iterator(); 75 76 while(it.hasNext()) 77 { 78 Object obj = it.next(); 79 80 if(!newAl.contains(obj))//底层调用元素equals方法。 81 newAl.add(obj); 82 83 } 84 return newAl; 85 } 86 } 87 ---------- java ---------- 88 lisi02和lisi01比一下 89 lisi02和lisi01比一下 90 lisi02和lisi02比一下 91 lisi03和lisi01比一下 92 lisi03和lisi02比一下 93 lisi04和lisi01比一下 94 lisi04和lisi02比一下 95 lisi04和lisi03比一下 96 lisi01::30 97 lisi02::32 98 lisi03::33 99 lisi04::35 100 101 输出完成 (耗时 0 秒) - 正常终止
Set接口
Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。
|--HashSet:底层数据结构是哈希表。线程是非同步的。
保证元素唯一性的原理:
通过元素的两个方法,hashCode和equals来完成。
先判断元素的hashCode值是否相同。如果相同,继续判断元素的equals方法,是否为true。如果元素的hashcode值不同,则不会调用equals。
|--TreeSet:底层数据结构是二叉树。可以对Set集合中的元素进行排序。
保证元素唯一性的依据:
compareTo方法return 0。
TreeSet排序的第一种方式:
让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。也种方式也成为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式:
当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。
HashSet练习,往HashSet集合中存入自定对象人,姓名和年龄相同为重复元素,演示了判断元素唯一性的原理。
1 import java.util.*; 2 class HashSetTest 3 { 4 public static void main(String[] args) 5 { 6 HashSet hs = new HashSet(); 7 8 9 hs.add(new Person("a1",11)); 10 hs.add(new Person("a2",12)); 11 hs.add(new Person("a3",13)); 12 hs.add(new Person("a2",12)); 13 hs.add(new Person("a4",14)); 14 15 hs.remove(new Person("a4",14)); 16 17 Iterator it = hs.iterator(); 18 19 while(it.hasNext()) 20 { 21 Person p = (Person)it.next(); 22 System.out.println(p.getName()+"::"+p.getAge()); 23 } 24 25 } 26 } 27 class Person 28 { 29 private String name; 30 private int age; 31 Person(String name,int age) 32 { 33 this.name = name; 34 this.age = age; 35 } 36 //为了获得对象独特的哈希值,避免equals判断,提高效率,创建对象时复写hashCode和equals方法 37 public int hashCode() 38 { 39 System.out.println(this.name+"....hashCode"); 40 return name.hashCode()+age*37; 41 } 42 43 public boolean equals(Object obj) 44 { 45 46 if(!(obj instanceof Person)) 47 return false; 48 49 Person p = (Person)obj; 50 System.out.println(this.name+"...equals.."+p.name); 51 52 return this.name.equals(p.name) && this.age == p.age; 53 } 54 public String getName() 55 { 56 return name; 57 } 58 public int getAge() 59 { 60 return age; 61 } 62 } 63 ---------- java ---------- 64 a1....hashCode 65 a2....hashCode 66 a3....hashCode//a1,a2,a3算完哈希值没有相同的存入HashSet 67 a2....hashCode 68 a2...equals..a2//重复的a2算完哈希值发现相同,调用equals比较内容,发现相同视为重复元素未存。 69 a4....hashCode 70 a4....hashCode 71 a4...equals..a4//remove方法同样调用hashCode和equals方法 72 a1::11 73 a3::13 74 a2::12//元素是无序的。 75 76 输出完成 (耗时 0 秒) - 正常终止
TreeSet练习,往TreeSet集合中存储自定义对象人。按人的年龄进行排序。
TreeSet排序的第一种方式:
让元素自身具备比较性。元素实现Comparable接口,覆盖compareTo方法。
1 import java.util.*; 2 class TreeSetDemo1 3 { 4 public static void main(String[] args) 5 { 6 TreeSet ts = new TreeSet(); 7 8 ts.add(new Person("lisi02",22)); 9 ts.add(new Person("lisi007",20)); 10 ts.add(new Person("lisi09",19)); 11 ts.add(new Person("lisi08",19)); 12 ts.add(new Person("lisi007",20)); 13 14 15 Iterator it = ts.iterator(); 16 while(it.hasNext()) 17 { 18 Person p = (Person)it.next(); 19 System.out.println(p.getName()+"..."+p.getAge()); 20 } 21 } 22 } 23 class Person implements Comparable//该接口强制让Person具备比较性。 24 { 25 private String name; 26 private int age; 27 28 Person(String name,int age) 29 { 30 this.name = name; 31 this.age = age; 32 } 33 public int compareTo(Object obj) 34 { 35 //return 1;//存取顺序一致 36 if(!(obj instanceof Person)) 37 throw new RuntimeException("不是人这一类的对象"); 38 Person p = (Person)obj; 39 40 System.out.println(this.name+"....compareto....."+p.name); 41 if(this.age>p.age) 42 return 1; 43 if(this.age==p.age) 44 { 45 return this.name.compareTo(p.name);//String类已经实现了Comparable接口 46 } 47 return -1; 48 49 } 50 public String getName() 51 { 52 return name; 53 54 } 55 public int getAge() 56 { 57 return age; 58 } 59 } 60 ---------- java ---------- 61 lisi02....compareto.....lisi02 62 lisi007....compareto.....lisi02 63 lisi09....compareto.....lisi02 64 lisi09....compareto.....lisi007 65 lisi08....compareto.....lisi007 66 lisi08....compareto.....lisi09 67 lisi08...19 68 lisi09...19 69 lisi007...20 70 lisi02...22 71 72 输出完成 (耗时 0 秒) - 正常终止
TreeSet的第二种排序方式:
当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。定义一个比较器,实现Comparator接口,覆盖compare()方法(返回值是正数、负数和0),将比较器对象作为参数传递给TreeSet集合的构造函数。
1 import java.util.*; 2 //当两种排序都存在时,以比较器为主。主要条件判断完了判断次要条件,防止元素丢失。 3 class Person implements Comparable 4 { 5 private String name; 6 private int age; 7 8 Person(String name,int age) 9 { 10 this.name = name; 11 this.age = age; 12 } 13 14 public int compareTo(Object obj) 15 { 16 17 if(!(obj instanceof Person)) 18 throw new RuntimeException("不是人这一类的对象"); 19 Person p = (Person)obj; 20 21 if(this.age>p.age) 22 return 1; 23 if(this.age==p.age) 24 { 25 return this.name.compareTo(p.name); 26 } 27 return -1; 28 29 } 30 31 public String getName() 32 { 33 return name; 34 35 } 36 public int getAge() 37 { 38 return age; 39 } 40 } 41 class TreeSetDemo2 42 { 43 public static void main(String[] args) 44 { 45 TreeSet ts = new TreeSet(new MyCompare());//TreeSet集合的构造函数接收比较器对象 46 47 ts.add(new Person("lisi02",22)); 48 ts.add(new Person("lisi02",21)); 49 ts.add(new Person("lisi007",20)); 50 ts.add(new Person("lisi09",19)); 51 ts.add(new Person("lisi06",18)); 52 ts.add(new Person("lisi06",18)); 53 ts.add(new Person("lisi007",29)); 54 55 56 Iterator it = ts.iterator(); 57 while(it.hasNext()) 58 { 59 Person p = (Person)it.next(); 60 System.out.println(p.getName()+"..."+p.getAge()); 61 } 62 } 63 } 64 65 class MyCompare implements Comparator//定义一个比较器,实现Comparator接口,覆盖compare()方法 66 { 67 public int compare(Object o1,Object o2) 68 { 69 Person p1 = (Person)o1; 70 Person p2 = (Person)o2; 71 72 int num = p1.getName().compareTo(p2.getName()); 73 if(num==0) 74 { 75 76 return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));//封装Integer对象调用compareTo方法 77 /* 78 if(p1.getAge()>p2.getAge()) 79 return 1; 80 if(p1.getAge()==p2.getAge()) 81 return 0; 82 return -1; 83 */ 84 } 85 return num; 86 } 87 } 88 ---------- java ---------- 89 lisi007...20 90 lisi007...29 91 lisi02...21 92 lisi02...22 93 lisi06...18 94 lisi09...19 95 96 输出完成 (耗时 0 秒) - 正常终止
二叉树排序示例
创建排序二叉树的步骤,也就是不断地向排序二叉树添加节点的过程,向排序二叉树添加节点的步骤如下:
- 以根节点当前节点开始搜索。
- 拿新节点的值和当前节点的值比较。
- 如果新节点的值更大,则以当前节点的右子节点作为新的当前节点;如果新节点的值更小,则以当前节点的左子节点作为新的当前节点。
- 重复 2、3 两个步骤,直到搜索到合适的叶子节点为止。
- 将新节点添加为第 4 步找到的叶子节点的子节点;如果新节点更大,则添加为右子节点;否则添加为左子节点。
Map
Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。一个映射不能包含重复的键,每个键最多只能映射到一个值。Collection是单列集合(“单身汉”),Map是双列集合(“夫妻”)。
Map
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。
|--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。用作键的对象必须实现hashCode方法和equals方法。将Hashtable替代,jdk1.2.效率高。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
Map和Set很像,其实Set底层就是使用了Map集合。
1,添加。
put(K key, V value)
putAll(Map<? extends K,? extends V> m)
2,删除。
clear()
remove(Object key)
3,判断。
containsValue(Object value)
containsKey(Object key)
isEmpty()
4,获取。
get(Object key)
size()
values()
entrySet()
keySet()
1 import java.util.*; 2 class MapDemo 3 { 4 public static void main(String[] args) 5 { 6 Map<String,String> map = new HashMap<String,String>(); 7 8 //添加元素,添加元素,如果出现添加时,相同的键。那么后添加的值会覆盖原有键对应值。 9 //并put方法会返回被覆盖的值。 10 System.out.println("put:"+map.put("01","zhangsan1")); 11 System.out.println("put:"+map.put("01","wnagwu")); 12 map.put("02","zhangsan2"); 13 map.put("03","zhangsan3"); 14 15 System.out.println("containsKey:"+map.containsKey("02")); 16 System.out.println("remove:"+map.remove("02")); 17 18 System.out.println("get:"+map.get("01")); 19 20 map.put("04",null); 21 System.out.println("get:"+map.get("04")); 22 //可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。 23 24 25 26 //获取map集合中所有的值。 27 Collection<String> coll = map.values(); 28 29 System.out.println(coll); 30 System.out.println(map); 31 } 32 } 33 ---------- java ---------- 34 put:null 35 put:zhangsan1 36 containsKey:true 37 remove:zhangsan2 38 get:wnagwu 39 get:null 40 [null, wnagwu, zhangsan3] 41 {04=null, 01=wnagwu, 03=zhangsan3} 42 43 输出完成 (耗时 0 秒) - 正常终止
Map集合的两种取出方式:
1,Set<k> keySet:
将map中所有的键存入到Set集合。因为set具备迭代器。所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。
1 import java.util.*; 2 class MapDemo1 3 { 4 public static void main(String[] args) 5 { 6 Map<String,String> map = new HashMap<String,String>(); 7 8 map.put("02","zhangsan2"); 9 map.put("03","zhangsan3"); 10 map.put("01","zhangsan1"); 11 map.put("04","zhangsan4"); 12 13 14 //先获取map集合的所有键的Set集合,keySet(); 15 Set<String> keySet= map.keySet(); 16 17 //有了Set集合。就可以获取其迭代器。 18 Iterator<String> it = keySet.iterator(); 19 20 while(it.hasNext()) 21 { 22 String key = it.next(); 23 //有了键可以通过map集合的get方法获取其对应的值。 24 String value = map.get(key); 25 System.out.println(key+":"+value); 26 } 27 } 28 }
2,Set<Map.Entry<k,v>> entrySet:
将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry。Entry其实就是Map中的一个static内部接口。为什么要定义在内部呢?因为只有有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。而且该事物在直接访问Map集合中的元素。
1 import java.util.*; 2 class MapDemo2 3 { 4 public static void main(String[] args) 5 { 6 Map<String,String> map = new HashMap<String,String>(); 7 8 map.put("02","zhangsan2"); 9 map.put("03","zhangsan3"); 10 map.put("01","zhangsan1"); 11 map.put("04","zhangsan4"); 12 13 //将Map集合中的映射关系取出。存入到Set集合中。 14 Set<Map.Entry<String,String>> entrySet = map.entrySet(); 15 16 Iterator<Map.Entry<String,String>> it = entrySet.iterator(); 17 18 while(it.hasNext()) 19 { 20 Map.Entry<String,String> me = it.next();//Map.Entry也是一个接口,它是Map接口中的一个内部接口。 21 String key = me.getKey(); 22 String value = me.getValue(); 23 24 System.out.println(key+":"+value); 25 } 26 } 27 }
练习。获取字符串中的字母出现的次数。打印结果:a(1)c(2).....
通过结果发现,每一个字母都有对应的次数。说明字母和次数之间都有映射关系,可以选择map集合,因为map集合中存放就是映射关系。
思路:
1,将字符串转换成字符数组。因为要对每一个字母进行操作。
2,定义一个map集合,因为打印结果的字母有顺序,所以使用Treemap集合。
3,遍历字符数组。
将每一个字母作为键去查map集合。如果返回null,将该字母和1存入到map集合中。如果返回不是null,说明该字母在map集合已经存在并有对应次数。那么就获取该次数并进行自增。然后将该字母和自增后的次数存入到map集合中。覆盖掉原来键所对应的值。
4,将map集合中的数据变成指定的字符串形式返回。
1 import java.util.*; 2 class MapTest 3 { 4 public static void main(String[] args) 5 { 6 String s= charCount("sddf—g+AzxBc,.CCTVxcvdf"); 7 System.out.println(s); 8 } 9 10 public static String charCount(String str) 11 { 12 char[] chs = str.toCharArray();//将字符串转换成字符数组 13 14 TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>(); 15 //定义一个map集合,因为打印结果的字母有顺序,所以使用Treemap集合 16 17 int count = 0; 18 for(int x=0; x<chs.length; x++) 19 { 20 if(!(chs[x]>='a' && chs[x]<='z' || chs[x]>='A' && chs[x]<='Z')) 21 continue;//如果范围不在字母之间,继续循环。 22 23 Integer value = tm.get(chs[x]);//将每一个字母作为键去查map集合 24 25 //如果返回null,将该字母和0自增后的1存入到map集合中。 26 //如果返回不是null,说明该字母在map集合已经存在并有对应次数。那么就获取该次数并进行自增,然后将该字母和自增后的次数存入到map集合中。覆盖掉原来键所对应的值。 27 if(value!=null) 28 count = value; 29 count++; 30 tm.put(chs[x],count);//直接往集合中存储字符和数字,为什么可以,因为自动装箱。 31 32 count = 0;//遍历完一个字母后计数器清零。 33 } 34 35 StringBuilder sb = new StringBuilder(); 36 //Map集合取出 37 //将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry 38 Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet(); 39 Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator(); 40 41 while(it.hasNext()) 42 { 43 Map.Entry<Character,Integer> me = it.next(); 44 Character ch = me.getKey(); 45 Integer value = me.getValue(); 46 sb.append(ch+"("+value+")"); 47 } 48 return sb.toString(); 49 } 50 } 51 ---------- java ---------- 52 A(1)B(1)C(2)T(1)V(1)c(2)d(3)f(2)g(1)s(1)v(1)x(2)z(1) 53 //Character类实现了Comparable,默认自然顺序排列 54 输出完成 (耗时 0 秒) - 正常终止
Map扩展
例如一个学校有多个教室。每一个教室都有名称。一个教室很多学生。学生封装成对象。
映射关系:
key value
"yureban"-----》 yure Student("01" "zhangsan"); //List集合
Student("02" "lisi");
"jiuyeban"-----》jiuye Student("01" "zhaoliu");
Student("02" "wangwu");
1 /* 2 map扩展知识。 3 map集合被使用是因为具备映射关系。 4 一个学校有多个教室。每一个教室都有名称。一个教室很多学生。学生封装成对象。 5 */ 6 import java.util.*; 7 class Student 8 { 9 private String id; 10 private String name; 11 Student(String id,String name) 12 { 13 this.id = id; 14 this.name = name; 15 } 16 public String toString() 17 { 18 return id+":::"+name; 19 } 20 } 21 class MapDemo3 22 { 23 public static void main(String[] args) 24 { 25 demo(); 26 } 27 28 public static void demo() 29 { 30 HashMap<String,List<Student>> czbk = new HashMap<String,List<Student>>(); 31 //学生对象封装到List集合中 32 List<Student> yure = new ArrayList<Student>(); 33 List<Student> jiuye = new ArrayList<Student>(); 34 35 czbk.put("yureban",yure); 36 czbk.put("jiuyeban",jiuye); 37 38 yure.add(new Student("01","zhangsan")); 39 yure.add(new Student("02","lisi")); 40 jiuye.add(new Student("01","zhaoliu")); 41 jiuye.add(new Student("02","wangwu")); 42 44 Iterator<String> it = czbk.keySet().iterator(); 45 46 while(it.hasNext()) 47 { 48 String roomName = it.next(); 49 List<Student> room = czbk.get(roomName);//班级房间返回List集合 50 51 System.out.println(roomName); 52 getInfos(room);//拿到房间名调用getInfos()取出封装的学生集合 53 } 54 55 } 56 public static void getInfos(List<Student> list) 57 { 58 Iterator<Student> it = list.iterator(); 59 while(it.hasNext()) 60 { 61 Student s = it.next(); 62 System.out.println(s); 63 } 64 } 65 } 66 ---------- java ---------- 67 jiuyeban 68 01:::zhaoliu 69 02:::wangwu 70 yureban 71 01:::zhangsan 72 02:::lisi 73 74 输出完成 (耗时 0 秒) - 正常终止
集合工具类
Collections:集合框架的工具类。里面定义的都是静态方法。提供的方法中有可以对list集合进行排序,二分查找等方法。因为要提高效率,通常常用的集合都是线程不安全的。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
static
|
sort(List<T> list)
根据元素的自然顺序 对指定列表按升序进行排序。 |
|
static
|
sort(List<T> list,
Comparator<? super T> c)
根据指定比较器产生的顺序对指定列表进行排序 |
1 /* 2 Collections:sort 3 list集合排序演示 4 */ 5 import java.util.*; 6 class CollectionsSortDemo 7 { 8 public static void main(String[] args) 9 { 10 sortDemo(); 11 12 } 13 public static void sortDemo() 14 { 15 List<String> list = new ArrayList<String>(); 16 17 list.add("abcd"); 18 list.add("aaa"); 19 list.add("zz"); 20 list.add("kkkkk"); 21 list.add("qq"); 22 list.add("z"); 23 24 System.out.println("原集合..."+list); 25 26 Collections.sort(list); 27 System.out.println("自然排序..."+list); 28 Collections.sort(list,new StrLenComparator()); 29 System.out.println("长度排序..."+list); 30 } 31 } 32 class StrLenComparator implements Comparator<String> 33 { 34 public int compare(String s1,String s2) 35 { 36 if(s1.length()>s2.length()) 37 return 1; 38 if(s1.length()<s2.length()) 39 return -1; 40 return s1.compareTo(s2); 41 } 42 } 43 ---------- java ---------- 44 原集合...[abcd, aaa, zz, kkkkk, qq, z] 45 自然排序...[aaa, abcd, kkkkk, qq, z, zz]//调用Collections的sort方法给list集合按自然顺序排序 46 长度排序...[z, qq, zz, aaa, abcd, kkkkk]//调用Collections的sort方法接收一个list集合和自定义的比较器,给list集合按字符串长度排序。 47 48 输出完成 (耗时 0 秒) - 正常终止
static void |
swap(List<?> list, int i, int j) 在指定列表的指定位置处交换元素。 |
static
|
max(Collection<? extends
T> coll) 根据元素的自然顺序,返回给定 collection 的最大元素。 |
|
static
|
max(Collection<? extends T> coll,
Comparator<? super
T> comp) 根据指定比较器产生的顺序,返回给定 collection 的最大元素。 |
|
static
|
min(Collection<? extends
T> coll) 根据元素的自然顺序 返回给定 collection 的最小元素。 |
|
static
|
min(Collection<? extends T> coll,
Comparator<? super
T> comp) 根据指定比较器产生的顺序,返回给定 collection 的最小元素。 |
1 /* 2 集合框架的工具类。 3 Collections:max min swap 5 */ 6 import java.util.*; 7 class CollectionsMaxMinDemo 8 { 9 public static void main(String[] args) 10 { 11 maxDemo(); 13 } 14 public static void maxDemo() 15 { 16 List<String> list = new ArrayList<String>(); 17 18 list.add("abcd"); 19 list.add("aaa"); 20 list.add("zz"); 21 list.add("kkkkk"); 22 list.add("qq"); 23 list.add("z"); 24 Collections.sort(list); 25 sop(list); 26 String max = Collections.max(list); 27 sop("Max="+max); 28 String min = Collections.min(list); 29 sop("Min="+min); 30 31 Collections.sort(list,new StrLenComparator()); 32 sop(list); 33 String max1 = Collections.max(list,new StrLenComparator()); 34 sop("Max1="+max1); 35 String min1 = Collections.min(list,new StrLenComparator()); 36 sop("Min1="+min1); 37 38 Collections.swap(list,0,list.size()-1);//头尾交换 39 sop("swap......"+list); 43 } 44 45 public static void sop(Object obj) 46 { 47 System.out.println(obj); 48 } 49 } 52 class StrLenComparator implements Comparator<String> 53 { 54 public int compare(String s1,String s2) 55 { 56 if(s1.length()>s2.length()) 57 return 1; 58 if(s1.length()<s2.length()) 59 return -1; 60 return s1.compareTo(s2); 61 } 62 } 63 ---------- java ---------- 64 [aaa, abcd, kkkkk, qq, z, zz] 65 Max=zz 66 Min=aaa 67 [z, qq, zz, aaa, abcd, kkkkk] 68 Max1=kkkkk 69 Min1=z 70 swap......[kkkkk, qq, zz, aaa, abcd, z] 71 72 输出完成 (耗时 0 秒) - 正常终止
static
|
binarySearch(List<? extends Comparable<? super T>> list, T key) 使用二分搜索法搜索指定列表,以获得指定对象。 |
|
static
|
binarySearch(List<? extends
T> list, T key, Comparator<? super T> c)
使用二分搜索法搜索指定列表,以获得指定对象。 |
1 /* 2 集合框架的工具类。 3 Collections: 4 binarySearch二分查找 5 */ 6 import java.util.*; 7 class CollectionsBinarySearchDemo 8 { 9 public static void main(String[] args) 10 { 11 binarySearchDemo(); 12 13 } 14 public static void sop(Object obj) 15 { 16 System.out.println(obj); 17 } 18 19 public static void binarySearchDemo() 20 { 21 List<String> list = new ArrayList<String>(); 22 23 list.add("abcd"); 24 list.add("aaa"); 25 list.add("zz"); 26 list.add("kkkkk"); 27 list.add("qq"); 28 list.add("z"); 29 Collections.sort(list); 30 sop(list); 31 int index = Collections.binarySearch(list,"WW"); 32 sop("index="+index); 33 Collections.sort(list,new StrLenComparator()); 34 sop(list); 35 int index1 = Collections.binarySearch(list,"ww",new StrLenComparator()); 36 sop("index1="+index1); 37 } 38 } 39 class StrLenComparator implements Comparator<String> 40 { 41 public int compare(String s1,String s2) 42 { 43 if(s1.length()>s2.length()) 44 return 1; 45 if(s1.length()<s2.length()) 46 return -1; 47 return s1.compareTo(s2); 48 } 49 } 50 ---------- java ---------- 51 [aaa, abcd, kkkkk, qq, z, zz] 52 index=-1//如果搜索键包含在列表中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。 53 [z, qq, zz, aaa, abcd, kkkkk] 54 index1=-3 55 56 输出完成 (耗时 0 秒) - 正常终止
static
|
fill(List<? super T> list, T obj) 使用指定元素替换指定列表中的所有元素。 |
1 /*Collections: 2 fill使用指定元素替换指定列表中的所有元素。 3 自定义fill替换部分元素 4 */ 5 import java.util.*; 6 class CollectionsFillDemo 7 { 8 public static void sop(Object obj) 9 { 10 System.out.println(obj); 11 } 12 public static void main(String[] args) 13 { 14 List<String> list = new ArrayList<String>(); 15 list.add("abcd"); 16 list.add("aaa"); 17 list.add("zz"); 18 list.add("kkkkk"); 19 list.add("z"); 20 sop(list); 21 Collections.fill(list,"xx");//使用指定元素替换指定列表中的所有元素。 22 sop(list); 23 fillDemo(list,"qq",1,3); 24 } 25 26 //自定义方法将list集合中部分元素替换。 27 public static void fillDemo(List<String> list,String str,int index_s,int index_e) 28 { 29 //调用list的subList方法取得子集合 30 List<String> newlist = list.subList(index_s,index_e); 31 //把子集合中对象全部替换为str。 32 Collections.fill(newlist,str); 33 sop(list); 34 } 35 } 36 ---------- java ---------- 37 [abcd, aaa, zz, kkkkk, z] 38 [xx, xx, xx, xx, xx] 39 [xx, qq, qq, xx, xx] 40 41 输出完成 (耗时 0 秒) - 正常终止
static
|
replaceAll(List<T> list, T oldVal, T newVal) 使用另一个值替换列表中出现的所有某一指定值。 |
1 import java.util.*; 2 class CollectionsReplaceAllDemo 3 { public static void sop(Object obj) 4 { 5 System.out.println(obj); 6 } 7 public static void main(String[] args) 8 { 9 replaceAllDemo(); 10 } 11 12 public static void replaceAllDemo() 13 { 14 List<String> list = new ArrayList<String>(); 15 16 list.add("abcd"); 17 list.add("aaa"); 18 list.add("aaa"); 19 list.add("aaa"); 20 list.add("zz"); 21 list.add("kkkkk"); 22 sop("原集合"+list); 23 24 Collections.replaceAll(list,"aaa","pp"); 25 sop(list); 26 } 27 } 28 ---------- java ---------- 29 原集合[abcd, aaa, aaa, aaa, zz, kkkkk] 30 [abcd, pp, pp, pp, zz, kkkkk] 31 32 输出完成 (耗时 0 秒) - 正常终止
static void |
reverse(List<?> list) 反转指定列表中元素的顺序。 |
|
static
|
reverseOrder()
返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。 |
|
static
|
reverseOrder(Comparator<T> cmp)
返回一个比较器,它强行逆转指定比较器的顺序。 |
1 import java.util.*; 2 class StrLenComparator implements Comparator<String> 3 { 4 public int compare(String s1,String s2) 5 { 6 if(s1.length()>s2.length()) 7 return 1; 8 if(s1.length()<s2.length()) 9 return -1; 10 return s1.compareTo(s2); 11 } 12 } 13 class CollectionsReverseOrderDemo 14 { 15 public static void main(String[] args) 16 { 17 orderDemo(); 18 } 19 20 public static void orderDemo() 21 { 22 TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new StrLenComparator())); 23 //返回一个比较器,它强行逆转指定比较器的顺序。TreeSet构造函数接收这一比较器进行排序。 24 ts.add("abcde"); 25 ts.add("aaa"); 26 ts.add("k"); 27 ts.add("cc"); 28 29 Iterator it = ts.iterator(); 30 while(it.hasNext()) 31 { 32 System.out.println(it.next()); 33 } 34 } 35 } 36 ---------- java ---------- 37 abcde 38 aaa 39 cc 40 k 41 42 输出完成 (耗时 0 秒) - 正常终止
static void |
shuffle(List<?> list) 使用默认随机源对指定列表进行置换。 |
static void |
shuffle(List<?> list,
Random rnd)
使用指定的随机源对指定列表进行置换。 |
1 import java.util.*; 2 class CollectionsShuffleDemo 3 { 4 public static void main(String[] args) 5 { 6 shuffleDemo(); 7 } 8 public static void shuffleDemo() 9 { 10 List<String> list = new ArrayList<String>(); 11 12 list.add("abcd"); 13 list.add("aaa"); 14 list.add("zz"); 15 list.add("kkkkk"); 16 list.add("qq"); 17 list.add("z"); 18 19 System.out.println(list); 20 Collections.shuffle(list); 21 System.out.println(list); 22 } 23 } 24 ---------- java ---------- 25 [abcd, aaa, zz, kkkkk, qq, z] 26 [kkkkk, qq, z, abcd, aaa, zz] 27 28 输出完成 (耗时 0 秒) - 正常终止
Collections中返回线程安全的集合的方法
static
|
synchronizedCollection(Collection<T> c) 返回指定 collection 支持的同步(线程安全的)collection。 |
|
static
|
synchronizedList(List<T> list)
返回指定列表支持的同步(线程安全的)列表。 |
|
static
|
synchronizedMap(Map<K,V> m)
返回由指定映射支持的同步(线程安全的)映射。 |
|
static
|
synchronizedSet(Set<T> s) 返回指定 set 支持的同步(线程安全的)set。 |
Arrays:此类包含用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂。
数组变集合
1 /* 2 Arrays:用于操作数组的工具类。 3 里面都是静态方法。 4 asList:将数组变成list集合 5 把数组变成list集合有什么好处?可以使用集合的思想和方法来操作数组中的元素。 6 7 注意:将数组变成集合,不可以使用集合的增删方法。因为数组的长度是固定。如果你增删。那么会反生UnsupportedOperationException. 8 contains。 9 get 10 indexOf() 11 subList(); 12 */ 13 import java.util.*; 14 class ArraysDemo 15 { 16 public static void main(String[] args) 17 { 18 19 String[] arr = {"abc","cc","kkkk"}; 20 21 22 List<String> list = Arrays.asList(arr); 23 //list.add("qq"); //异常UnsupportedOperationException 24 System.out.println(list); 25 26 int[] nums1 = {2,4,5}; 27 List<int[]> list1 = Arrays.asList(nums1); 28 System.out.println(list1); 29 30 Integer[] nums2 = {2,4,5}; 31 List<Integer> list2 = Arrays.asList(nums2); 32 System.out.println(list2); 33 34 /* 35 如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。 36 如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。 37 */ 38 } 39 } 40 ---------- java ---------- 41 [abc, cc, kkkk] 42 [[I@3e0ebb] 43 [2, 4, 5] 44 45 输出完成 (耗时 0 秒) - 正常终止
集合变数组
Collection接口中的toArray方法。
1 /* 2 集合变数组。 3 Collection接口中的toArray方法。 4 */ 5 import java.util.*; 6 class CollectionToArray 7 { 8 public static void main(String[] args) 9 { 10 ArrayList<String> al = new ArrayList<String>(); 11 12 al.add("abc1"); 13 al.add("abc2"); 14 al.add("abc3"); 15 16 /* 17 1,指定类型的数组到底要定义多长呢? 18 当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。 19 当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组。 20 所以创建一个刚刚好的数组最优。 21 22 2,为什么要将集合变数组? 23 为了限定对元素的操作。不需要进行增删了。 24 */ 25 26 String[] arr = al.toArray(new String[al.size()]); 27 28 System.out.println(Arrays.toString(arr)); 29 } 30 } 31 ---------- java ---------- 32 [abc1, abc2, abc3] 33 34 输出完成 (耗时 0 秒) - 正常终止