------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。数组很难对其数据进行操作,而集合可以很方便对存储的对象进行增删改查等操作。可以说集合比数组功能更加强大而且使用起来也更加方便。所以我们有必要深入的学习一下集合类。
集合的特点:
(1)、用于存储对象的容器
(2)、集合的长度是可变的
(3)、集合中不可以存储基本数据类型值
(4)、集合中存储的都是对象的引用(地址)
根据数据结构的不同,可以分为不同的集合(容器)。下图是集合框架构成图。
从途中可以看出集合类主要分为两大接口:1、Collection接口 2、Map接口。
Collection接口
"--List集合:元素都是有序的(存入和取出的顺序一致),元素是可以重复的,因为该集合体系具有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度快,但增删稍慢,线程不同步。
|--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢,线程不同步。
|--Vector:底层是数组数据结构,线程同步,已被ArrayList替代了,因为效率低。
|--Set集合:元素是无序的(存入和取出的顺序不一定一致),元素不可重复。Set接口中的方法和Collection接口中的方法一致。
|--HashSet集合:底层数据结构是哈希表,线程不安全,不同步。
|--LinkedHashSet:底层是链式的哈希表,该集合特点:存入数据和取出数据顺序一致,而且元素不重复,线程不同步。
|--TreeSet:底层是二叉树数据结构,可以对Set集合中的元素进行排序,线程不同步。
Map接口
|--Hashtable集合:底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的,效率低。JDK1.0出现的。
|--Properties集合:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
|--HashMap集合:底层是哈希表数据结构,允许使用null键null值,该集合是不同步的。该集合替换了Hashtable集合,效率高。JDK1.2出现的。
|--LinkedHashMap集合:底层是链式的哈希表结构,使用LinkedHashMap存入和取出的顺序是一致的。
|--TreeMap集合:底层是二叉树数据结构,线程不同步。可以用于给Map集合中的键进行排序。
Java集合类大部分的都增加了泛型,已增加程序的安全性,以后会详细的介绍的。了解了集合类的大致下面我们具体的介绍这几大集合类。
Collection是集合框架中的常用接口。其下有两个子接口:List(列表),Set(集)。
1、Collection集合集成体系:
|--Lsit
|--ArrayList
|--LinkedList
|--Vector
|--Set
|--HashSet
|--LinkedHashSet
|--TreeSet
2、Collection接口常见的方法
(1)、添加元素
1 boolean add(Object obj);//往集合中添加元素 2 boolean addAll(Collection c);//将另一Collection集合中的所有元素添加进Collection集合中
(2)、删除元素
1 boolean remove(Object obj);//删除指定元素 2 boolean removeAll(Collection con);//调用者只保留另一集合中没有的元素 3 void clear();//清空Collection集合全部元素
(3)、判断
1 boolean contains(Object obj);//判断集合中是否包含指定元素 2 boolean containsAll();//判断此Collection集合中是否包含另一个Collection集合 3 boolean isEmpty();//判断集合是否有元素
(4)、获取
1 int siez();//获取集合的大小,其实就是在判断集合是否为空 2 Iterator<E> iterator();//获取Collection集合的迭代器
(5)、获取交集
1 boolean retainAll(Collection c);//调用者只保留两集合的共性元素
(6)、集合变数组
1 Object[] toArray();//把集合转换成数组 2 <T> T[] toArray(T[] a);//把集合转换成数组
代码演示:
1 import java.util.*; 2 class CollectionDemo 3 { 4 public static void main(String[] args) 5 { 6 //因为Collection是接口无法创建对象,所以找子类来创建对象,多态的应用。 7 Collection<String> c1=new ArrayList<String>(); 8 Collection<String> c2=new ArrayList<String>(); 9 add(c1); 10 addAll(c1,c2); 11 remove(c1); 12 removeAll(c1,c2); 13 } 14 //演示add方法 15 public static void add(Collection<String> con){ 16 con.add("小明"); 17 con.add("赵四"); 18 con.add("王五"); 19 con.add("老王"); 20 con.add("黑马"); 21 con.add("安卓"); 22 //获取集合的大小 23 System.out.println("size="+con.size()); 24 //打印一下集合 25 System.out.println(con); 26 } 27 //演示addAll方法 28 public static void addAll(Collection<String> co1,Collection<String>co2){ 29 co1.add("小明"); 30 co1.add("赵四"); 31 co1.add("王五"); 32 co1.add("钱峰"); 33 34 co2.add("黑马"); 35 co2.add("赵四"); 36 co2.add("钱峰"); 37 //将co2中的元素添加到co1中 38 co1.addAll(co2); 39 System.out.println("addAll:"+co1); 40 41 //获取两个集合的交集,保留和指定的集合相同的元素 42 co1.retainAll(co2); 43 System.out.println("co1和co2取交集:"+co1); 44 } 45 //演示remove方法 46 public static void remove(Collection<String> con){ 47 con.add("小明"); 48 con.add("赵四"); 49 con.add("王五"); 50 con.add("老王"); 51 con.add("黑马"); 52 con.add("安卓"); 53 System.out.println(con.remove("老王")); 54 System.out.println(con.remove("java")); 55 System.out.println("remove:"+con); 56 57 //清空集合 58 con.clear(); 59 //判断集合是否为空 60 System.out.println("con是否为空:"+con.isEmpty()); 61 } 62 //演示removeAll方法 63 public static void removeAll(Collection<String> co1,Collection<String>co2){ 64 co1.add("小明"); 65 co1.add("赵四"); 66 co1.add("王五"); 67 co1.add("老王"); 68 69 co2.add("老王"); 70 co2.add("赵四"); 71 co2.add("钱峰"); 72 //从co1集合中删除与co2集合相同的元素 73 co1.removeAll(co2); 74 System.out.println("removeAll:"+co1); 75 } 76 77 }
3、Collection集合迭代器:Iterator<E>接口
迭代器:是一个接口。作用:用于取集合中的元素。
每一个集合都有自己的数据结构,都有特定的取出自己内部元素的方式。为了便于操作所有的容器,取出元素。将容器内部的取出方式按照一个统一的规则向外提供,这个规则就是Iterator接口。也就说,只要通过该接口就可以取出Collection集合中的元素,至于每一个具体的容器依据自己的数据结构,如何实现的具体取出细节,这个不用关心,这样就降低了取出元素和具体集合的耦合性。
注:在迭代时循环中next调用一次,就要hasNext判断一次。
获取Collection集中中元素的三种方式:
1 import java.util.*; 2 class CollectionDemo 3 { 4 public static void main(String[] args) 5 { 6 //因为Collection是接口无法创建对象,所以找子类来创建对象,多态的应用。 7 Collection<String> c=new ArrayList<String>(); 8 c.add("小明"); 9 c.add("黑马"); 10 c.add("安卓"); 11 c.add("小明"); 12 c.add("王五"); 13 //用Collection中的iterator()方法。调用集合中的迭代器方法,是为了获取集合中的迭代器对象。 14 //这种方式比较占用内存,因为循环结束后it变量还在内存中没有被释放 15 Iterator<String> it=c.iterator(); 16 while (it.hasNext()) 17 { 18 String name=it.next(); 19 System.out.println(name); 20 } 21 22 //建议使用这种方法,不消耗内存空间,it变量在for循环中,循环结束变量也就消失了 23 for (Iterator<String> it=c.iterator();it.hasNext() ; ) 24 {
//Iterator中不能使用add添加方法,因为没有该方法,只能删除(remove) 25 System.out.println(it.next()); 26 } 27 28 //这种方式是增强for循环,是Iterator迭代器的简写,但是这种方式有很大的弊端 29 //如果遍历Collection集合过程中还需要对元素进行操作,比如删除,需要使用迭代器。 30 for(String name:c){ 31 System.out.println(name); 32 33 } 34 }
迭代注意事项
(1)、迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)。
(2)、迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。
(3)、迭代器的next方法返回值类型是Object,所以要记得类型转换。加上泛型后则不需要转换。
List集合继承体系:
|--ArrayList
|--LinkedList
|--Vector
List本身是Collection接口的子接口,具备了Collection的所有方法。现在学习List体系特有的共性方法,查阅方法发现List的特有方法都有索引,这是该集合最大的特点。
凡是可以操作角标的方法都是该体系特有的方法。
1、List集合特有的方法
(1)、添加
1 void add(int index,E element);//在指定索引位置上添加元素 2 void addAll(int index,Collection<? extends E> c);//在指定索引位置上添加一堆元素
(2)、删除
1 Object remove(int index);//删除指定索引位置上的元素
(3)、修改
1 Object set(int index, E element);//对指定索引位进行元素的修改
(4)、获取
1 Object get(int index);//获取指定索引位置上的元素 2 int indexOf(Object obj);//获取指定元素第一次出现的索引位,如果该元素不存在返回-1;所以通过-1,可以判断一个元素是否存在。 3 int lastIndexOf(Object obj);//反向索引指定元素的位置。 4 List subList(int from,int to);//获取子列表,包含头不包含尾 5 Iterator listIterator();//List集合特有的迭代器 6 Iterator listIterator(int index);//从列表的指定位置开始返回List集合迭代器
注意:对于List集合,底层判断元素是否相同,其实用的是元素自身的equals方法完成的。所以建议元素都要复写equals方法,建立元素对象自己的比较相同的条件依据。
代码演示:
1 import java.util.*; 2 class ListDemo 3 { 4 public static void main(String[] args) 5 { 6 List<String> list=new ArrayList<String>(); 7 list.add("黑马"); 8 list.add("安卓"); 9 list.add("小明"); 10 list.add("王武"); 11 list.add("安卓"); 12 System.out.println("list:"+list); 13 //在指定位置上添加元素 14 list.add(3,"我爱黑马"); 15 System.out.println("listadd:"+list); 16 17 //删除指定位置上的元素 18 list.remove(4); 19 System.out.println("listremove:"+list); 20 21 //设置元素 22 System.out.println("listset:"+list.set(2,"我爱安卓")); 23 24 //获取指定位置上的元素 25 System.out.println("listget"+list.get(2)); 26 27 //获取元素第一次出现的位置。 28 System.out.println("indexOf="+list.indexOf("安卓")); 29 30 //获取子列表,包含头不包含尾 31 System.out.println(list.subList(2,4)); 32 } 33 34 }
2、List集合元素取出方式
(1)、List集合第一种取出方式:因为List集合有索引(角标)这个特殊的原因,所以List集合有自己特有的迭代方式,get方法。
1 import java.util.*; 2 class ListIteratorDemo 3 { 4 public static void main(String[] args) 5 { 6 List<String> list=new ArrayList<String>(); 7 list.add("黑马"); 8 list.add("安卓"); 9 list.add(".NET"); 10 list.add("IOS"); 11 //用集合的长度做循环条件,get方法取出元素 12 for (int x=0;x<list.size() ;x++ ) 13 { 14 System.out.println(list.get(x)); 15 } 16 } 17 }
(2)、List集合第二种取出方式:用Collection集合中的iterator()方法,这种方法有弊端只能遍历的过程中对集合删除操作。
1 import java.util.*; 2 class ListIteratorDemo 3 { 4 public static void main(String[] args) 5 { 6 List<String> list=new ArrayList<String>(); 7 list.add("黑马"); 8 list.add("安卓"); 9 list.add(".NET"); 10 list.add("IOS"); 11 //Collection接口中的iterator方法。 12 for (Iterator<String> it=list.iterator();it.hasNext() ; ) 13 { 14 String s=it.next(); 15 if(s.equals("IOS")){ 16 // list.add("JAVA");//ConcurrentModificationException异常,出现并发操作。 17 it.remove();//将IOS的引用从集合中删除了 18 } 19 System.out.println(s); 20 } 21 22 } 23 }
在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。Iterator方法是有限的,只能对元素进行判断,取出,删除的操作。那么如果想要其他的操作如添加,修改等,该怎么办呢?这时候就需要使用其子接口ListIterator,该接口只能通过List集合的ListIterator方法获取。
(3)、List集合取出方式第三种方式:Lsit集合特有迭代器:ListIterator
ListIterator迭代器中的方法:
1 import java.util.*; 2 class ListIteratorDemo 3 { 4 public static void main(String[] args) 5 { 6 List<String> list=new ArrayList<String>(); 7 list.add("黑马"); 8 list.add("安卓"); 9 list.add(".NET"); 10 list.add("IOS"); 11 //获取ListIterator迭代器对象 12 for (ListIterator<String> li=list.listIterator();li.hasNext() ; ) 13 { 14 //它可以实现在迭代过程中完成对元素的增删改查。 15 //注意:只有list集合具备该迭代功能。 16 String s=li.next(); 17 if(s.equals("IOS")) 18 li.add("JAVA");//增加元素 19 if(s.equals(".NET")) 20 li.remove();//删除元素 21 if(s.equals("安卓")) 22 li.set("JAVAEE");//修改元素 23 } 24 System.out.println(list); 25 26 } 27 }
1、ArrayList集合的方法和List集合的方法差不多一样。所以可参照List的方法。
2、LinkedList集合
LinkedList集合中特有的方法:
(1)、添加元素
1 addFirst();//将指定元素插入集合元素的开头 2 addLast();//将指定元素插入集合元素的末尾
------JDK1.6版本后新的方法----------------
1 offerFirst();//与addFirst方法没有区别 2 offerLast();//与addLast方法没有区别
(2)、获取但不删除元素
1 //获取但不删相互,如果链表为空,抛出NoSuchElementException 2 E getFirst();//返回此集合的第一个元素 3 E getLast();//返回此集合的最后一个元素
------JDK1.6版本后新的方法----------------
1 //获取但不移除,如果链表为空,返回null。 2 peekFirst(); 3 peekLast();
(3)、获取并删除元素
1 //获取并移除,如果链表为空,抛出NoSuchElementException。 2 E removeFirst();//移除并返回此集合的第一个元素 3 E removeLast();//移除并返回此集合的最后一个元素
------JDK1.6版本后新的方法----------------
1 //获取并移除,如果链表为空,返回null; 2 pollFirst(); 3 pollLast();
因为LinkedList中有特有的方法removeFirst()或者removeLast()(pollFirst、pollLast),所以LinkedList有4种迭代的方法。一种是:Iterator,一种是:iterator,一种是for循环遍历get方法,一种是LinkedList特有的方法。
1 //LinkedList特有取出方式 2 import java.util.*; 3 class LinkedListDemo 4 { 5 public static void main(String[] args) 6 { 7 LinkedList<String> list=new LinkedList<String>(); 8 list.add("黑马"); 9 list.add("安卓"); 10 list.add(".NET"); 11 list.add("IOS"); 12 while(!(list.isEmpty()))//通过判断集合是否为空来循环删除元素,知道为空停止循环 13 System.out.println(list.removeFirst()); //获取元素并且删除元素 14 } 15 }
3、Vector集合
(1)、Vector中特有的方法:
枚举就是Vector特有的取出方式。发现枚举和迭代器很像。其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。
1 //获取枚举接口的方法 2 Enumeration<E> elements();//返回此集合的枚举
而Eumeration枚举接口中的方法:
1 boolean hasMoreElements();//相当于Iterator中的hasNext() 2 E nextElement();//相当与Iterator中的next()
另外Collections集合工具类中也提供了Collection集合获取枚举接口的方法
1 static Enumeration< T> enumeratio(Collection<T> c);//返回一个指定 collection 上的枚举。
代码演示:
1 import java.util.*; 2 class VectorDemo 3 { 4 public static void main(String[] args) 5 { 6 Vector<String> v=new Vector<String>(); 7 v.add("黑马"); 8 v.add("安卓"); 9 v.add("IOS"); 10 v.add("JAVAEE"); 11 12 //用Iterator迭代器方法取出元素 13 for (Iterator<String> it=v.iterator();it.hasNext() ; ) 14 { 15 System.out.println(it.next()); 16 } 17 18 //用Enumeration枚举的方法取出元素 19 for (Enumeration<String> en=v.elements();en.hasMoreElements() ; ) 20 { 21 System.out.println(en.nextElement()); 22 } 23 24 //Collections.enumeration()方法获取枚举Enumeration接口 25 for (Enumeration<String> en=Collections.enumeration(v);en.hasMoreElements() ; ) 26 { 27 System.out.println(en.nextElement()); 28 } 29 } 30 }
4、List集合综合练习
(1)、请使用LinkedList来模拟一个堆栈或者队列数据结构。
堆栈:先进后出 First In Last Out FILO
队列:先进先出 First In First Out FIFO
思路:应该自定义一个LinkedList类,把要LinkedList封装到自己的类中。
1 import java.util.*; 2 class DuiLie 3 { 4 private LinkedList link; 5 //对象一初始化就创建了LinkedList集合 6 DuiLie(){ 7 link=new LinkedList(); 8 } 9 //队列的添加元素的功能。 10 public void myAdd(Object obj){ 11 link.addFirst(obj); 12 } 13 //队列的删除元素的功能。 14 public Object myRemove(){ 15 return link.removeLast(); 16 } 17 //判断队列是否为空 18 public boolean isNull(){ 19 return link.isEmpty(); 20 } 21 22 } 23 class DuiLieDemo 24 { 25 public static void main(String[] args) 26 { 27 DuiLie dl=new DuiLie(); 28 dl.myAdd("黑马"); 29 dl.myAdd("IOS"); 30 dl.myAdd("安卓"); 31 dl.myAdd(".NET"); 32 dl.myAdd("JAVAEE"); 33 while (!(dl.isNull())) 34 { 35 System.out.println(dl.myRemove()); 36 } 37 38 } 39 }
(2)、将自定义对象作为元素存到ArrayList集合中,并去除重复元素。比如:存人对象,同姓名同年龄,视为同一个人。为重复元素。
1 /* 2 List集合中必须定义一个新的容器来过滤重复元素. 3 而set集合则不用,因为set集合是无序的,不可重复的。 4 */ 5 import java.util.*; 6 class Person 7 { 8 private String name; 9 private int age; 10 Person(String name,int age) 11 { 12 this.name=name; 13 this.age=age; 14 } 15 public void setName(String name){ 16 this.name=name; 17 } 18 public String getName(){ 19 return name; 20 } 21 public void setAge(int age){ 22 this.age=age; 23 } 24 public int getAge(){ 25 return age; 26 } 27 public String toString(){ 28 return "name="+name+"....."+"age="+age; 29 } 30 public boolean equals(Object obj){//即使使用了泛型,equals方法中的参数也是Object obj, 31 if(!(obj instanceof Person))//因为复写的Object类中的方法,Object类的equals方法参数就是Object obj。 32 throw new RuntimeException("类型转换异常"); 33 Person p=(Person)obj; 34 return this.name.equals(p.name)&&this.age==p.age;//判断name和age是否相同 35 } 36 } 37 class ArrayListDemo 38 { 39 public static void main(String[] args) 40 { 41 List<Person> list=new ArrayList<Person>(); 42 list.add(new Person("黑马",120)); 43 list.add(new Person("安卓",110)); 44 list.add(new Person("IOS",45)); 45 list.add(new Person(".NET",97)); 46 list.add(new Person("JVAEE",12)); 47 list.add(new Person("IOS",45)); 48 list.add(new Person("黑马",120)); 49 //迭代原集合 50 printCollection(list); 51 System.out.println("---去除重复元素后的集合---------"); 52 list=getSingleElement(list); 53 printCollection(list); 54 55 } 56 public static List<Person> getSingleElement(List<Person> list){ 57 //1、定义一个临时容器用来装过滤后的数据 58 List<Person> newList=new ArrayList<Person>(); 59 //2、迭代list集合 60 for (Iterator<Person> it=list.iterator();it.hasNext() ;) 61 { 62 Person p=it.next(); 63 //3、判断被迭代到的元素是否在临时容器存在 64 //contains方法内部依靠的是equals方法,其实remove方法也调用equals方法的 65 if(!(newList.contains(p))) 66 newList.add(p); 67 } 68 return newList; 69 70 } 71 //迭代器取出集合中的元素 72 private static void printCollection(List<Person> list){ 73 for (Iterator<Person> it=list.iterator();it.hasNext() ; ) 74 { 75 System.out.println(it.next()); 76 } 77 } 78 }
Set接口中的方法和Collection中方法一致的。Set集合元素不可重复且无序。Set接口取出方式只有一种:迭代器。
Set集合继承体系
|--HashSet
|--LinkedHashSet
|--TreeSet
1 import java.util.*; 2 class SetDemo 3 { 4 public static void main(String[] args) 5 { 6 //Set集合无需并且不可重复,方法和Collection方法一样 7 Set<String> set=new HashSet<String>(); 8 set.add("黑马");//添加元素 9 set.add("JAVAEE"); 10 set.add("安卓"); 11 set.add("IOS"); 12 set.add(".NET"); 13 set.add("JAVAEE"); 14 set.remove("IOS");//删除元素 15 16 //Iterator迭代器取出元素 17 for (Iterator<String> it=set.iterator();it.hasNext() ; ) 18 { 19 System.out.println(it.next()); 20 } 21 } 22 }
(1)、HashSet集合
HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。
哈希表确定元素是否相同:因为集合本身不可重复的特点所以不用定义新的Set集合来存放不重复元素。
(1)、 先判断的是两个元素的哈希值是否相同。如果相同,再判断两个对象的内容是否相同。
(2)、 判断哈希值相同,其实判断的是对象的HashCode方法。判断内容相同,用的是equals方法。如果哈希值不同,不需要判断equals。
判断HastSet集合中的元素是否相同,一般要复写对象的hashCode方法和equals方法。
哈希表的原理:
(1)、对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值。
(2)、哈希值就是这个元素的位置。
(3)、如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就存储,在原来对象的哈希值基础 +1顺延。
(4)、存储哈希值的结构,我们称为哈希表。
(5)、既然哈希表是根据哈希值存储的,为了提高效率,最好保证对象的关键字是唯一的。 这样可以尽量少的判断关键字对应的对象是否相同,提高了哈希表的操作效率。
需求:往HashSet集合中存储Person对象。如果姓名和年龄相同,视为同一个人,视为相同元素。
1 /* 2 如果姓名和年龄相同,视为同一个人,视为相同元素 3 */ 4 5 import java.util.*; 6 class Person 7 { 8 private String name; 9 private int age; 10 Person(String name,int age) 11 { 12 this.name=name; 13 this.age=age; 14 } 15 public void setName(String name){ 16 this.name=name; 17 } 18 public String getName(){ 19 return name; 20 } 21 public void setAge(int age){ 22 this.age=age; 23 } 24 public int getAge(){ 25 return age; 26 } 27 public String toString(){ 28 return "name="+name+"....."+"age="+age; 29 } 30 public int hashCode(){//复写了hashCode方法 31 return name.hashCode()+age*37; 32 } 33 public boolean equals(Object obj){//即使使用了泛型,equals方法中的参数也是Object obj, 34 if(!(obj instanceof Person))//因为复写的Object类中的方法,Object类的equals方法参数就是Object obj。 35 throw new RuntimeException("类型转换异常"); 36 Person p=(Person)obj; 37 return this.name.equals(p.name)&&this.age==p.age;//建立了自己的比较方式 38 } 39 } 40 class HashSetDemo 41 { 42 public static void main(String[] args) 43 { 44 Set<Person> set=new HashSet<Person>(); 45 set.add(new Person("黑马",98)); 46 set.add(new Person("安卓",76)); 47 set.add(new Person("IOS",67)); 48 set.add(new Person(".NET",34)); 49 set.add(new Person("JAVAEE",21)); 50 set.add(new Person("IOS",67)); 51 set.add(new Person("安卓",76)); 52 for (Iterator<Person> it=set.iterator();it.hasNext() ; ) 53 { 54 System.out.println(it.next()); 55 } 56 } 57 }
2、LinkedHashSet集合
LinkedHashSet这个集合不仅存入的顺序和取出的顺序一致,并且该集合可以自动去除重复元素。
需求:数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}
1 import java.util.*; 2 class LinkedHashSetDemo 3 { 4 public static void main(String[] args) 5 { 6 int[] arr={4,2,4,6,1,2,4,7,8}; 7 Integer[] in=getSingleElement(arr); 8 for (int x=0;x<in.length ;x++ ) 9 { 10 if(x<in.length-1) 11 System.out.print(in[x]+","); 12 else 13 System.out.print(in[x]); 14 } 15 16 } 17 public static Integer[] getSingleElement(int[] arr){ 18 //无序变有序,并且去重 19 LinkedHashSet<Integer> lhs=new LinkedHashSet<Integer>(); 20 for (int x=0;x<arr.length ;x++ ) 21 { 22 lhs.add(arr[x]); 23 } 24 //集合变成数组返回 25 return (Integer[])lhs.toArray(new Integer[lhs.size()]); 26 } 27 }
3、TreeSet集合
用于对Set集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性。 如果元素不具备比较性,在运行时会发生ClassCastException异常。
TreeSet判断元素唯一性的方式:就是根据比较方法的返回结果是否为0,是0就是相同元素,不存。
TreeSet集合排序的两种方式:
(1)、TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo(T)方法。也种方式也成为元素的自然顺序,或者叫做默认顺序。
(2)、TreeSet的第二种排序方式:让集合具备比较性。当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。集合需要传入比较器(Comparator接口),让集合具备比较行为。定义一个Comparator的子类对象,复写compare(T o1, T o2)方法。 将该类对象作为参数传递给TreeSet集合的构造函数。如果自定义类实现了Comparable接口,并且TreeSet的构造函数中也传入了比较器,那么将以比较器的比较规则为准。记住,排序时,当主要条件相同时,一定判断一下次要条件。Comparable<T>、Comparator<T>都带着泛型的。第二种方式较为灵活。
注:只有TreeSet和TreeMap集合的构造函数能接收Comparator比较器。
需求:往TreeSet集合中存储Student对象,并按照学生的姓名排序。
第一种方式:让学生自身具备比较性,实现Comparable接口,复写compareTo方法
1 import java.util.*; 2 class Student implements Comparable<Student> 3 { 4 private String name; 5 private int age; 6 Student(String name,int age){ 7 this.name=name; 8 this.age=age; 9 } 10 public void setName(String name){ 11 this.name=name; 12 } 13 public String getName(){ 14 return name; 15 } 16 public void setAge(int age){ 17 this.age=age; 18 } 19 public int getAge(){ 20 return age; 21 } 22 public String toString(){ 23 return "name="+name+"....."+"age="+age; 24 } 25 //复写Comparable接口的compareTo方法 26 public int compareTo(Student stu){ 27 int num=this.name.compareTo(stu.name);//先按照姓名排序,如果姓名相同然后再按照年龄排序 28 if(num==0) 29 return new Integer(this.age).compareTo(new Integer(stu.age));//按照年龄排序 30 return num; 31 } 32 } 33 class TreeSetDemo 34 { 35 public static void main(String[] args) 36 { 37 Set<Student> set=new TreeSet<Student>(); 38 set.add(new Student("黑马",120)); 39 set.add(new Student("安卓",43)); 40 set.add(new Student("IOS",87)); 41 set.add(new Student(".NET",21)); 42 set.add(new Student("JAVAEE",12)); 43 set.add(new Student("PHP",98)); 44 set.add(new Student("黑马",34)); 45 for (Iterator<Student> it=set.iterator();it.hasNext() ; ) 46 { 47 System.out.println(it.next()); 48 } 49 } 50 }
第二种方式:学生自身不具备比较性,这时候就可以定义一个类实现Comparator接口,覆盖compare(T o1, T o2)方法。
1 //Student类接上例 2 //实现Comparator接口,复写compare方法。比较器 3 class StuComparator implements Comparator<Student> 4 { 5 public int compare(Student s1,Student s2){ 6 int num=s1.getAge()-s2.getAge();//先按照年龄排序 7 if(num==0) 8 return s1.getName().compareTo(s2.getName());//年龄相同的再按照姓名排序 9 return num; 10 } 11 } 12 class TreeSetDemo 13 { 14 public static void main(String[] args) 15 { 16 Set<Student> set=new TreeSet<Student>(new StuComparator());//两种方式同时存在以比较器为主 17 set.add(new Student("黑马",120)); 18 set.add(new Student("安卓",43)); 19 set.add(new Student("IOS",87)); 20 set.add(new Student(".NET",21)); 21 set.add(new Student("JAVAEE",12)); 22 set.add(new Student("PHP",98)); 23 set.add(new Student("黑马",34)); 24 for (Iterator<Student> it=set.iterator();it.hasNext() ; ) 25 { 26 System.out.println(it.next()); 27 } 28 } 29 }
练习:对字符串进行长度排序。
1 import java.util.*; 2 class LenComparator implements Comparator<String> 3 { 4 public int compare(String s1,String s2){ 5 int num=s1.length()-s2.length();//按照长度排序 6 return (num==0)?s1.compareTo(s2):num;//如果长度相同,按照字符串自然排序 7 } 8 } 9 class StringLength 10 { 11 public static void main(String[] args) 12 { 13 TreeSet<String> ts=new TreeSet<String>(new LenComparator()); 14 ts.add("aaaa"); 15 ts.add("zz"); 16 ts.add("nbag"); 17 ts.add("cba"); 18 ts.add("abc"); 19 for (Iterator it=ts.iterator();it.hasNext() ; ) 20 { 21 System.out.println(it.next()); 22 } 23 24 } 25 }
Map集合该集合存储键值对。一对一对往里存。而且要保证键的唯一性。Map也称为双列集合;Collection集合称为单列集合,Collection一次存一个元素。和Set很像,Set底层就是使用了Map集合。
Map集合继承体系:
|--Hashable
|--Properties
|--HashMap
|--LinkedHashMap
|--TreeMap
1、Map集合常用方法
(1)、添加元素
1 Value put(key,value);//返回前一个和key关联的值,如果没有返回null。如果出现添加相同的键,那么后添加的值会覆盖原有键对应的值,并且put方法会返回被覆盖的值
(2)、删除
1 void clear();//清空map集合 2 value remove(Object key);//根据指定的key删除这个键值对
(3)、判断
1 boolean containsKey(key);//判断集合中是否存在指定的键 2 boolean containsValue(value);//判断集合中是否存在指定的值 3 boolean isEmpty();//判断集合是否为null
(4)、获取
1 value get(Key);//通过键获取值,如果没有该键返回null,可以通过返回null来判断是否存在指定键。当然有特殊情况,就是在hashmap集合中,是可以存储null键null值的。 2 int size();//获取键值对个数,也就是Map集合的长度 3 Set<Key> keySet();//返回Set集合,该集合中存放的是Map集合中的全部键(Key)的值 4 Set<Map.Entry<Key,Value>> entrySet();//返回Set集合,该集合存放的是Map集合的映射关系,关系的数据类型就是:Map.Entry。 5 Collection<Value> values();//返回Collection集合,该集合中存放的是Map集合中的全部值。返回的Collection集合可以通过Iterator迭代器获取到全部值
map中是没有迭代器的,collection具备迭代器,只要将map集合转成Set集合,可以使用迭代器了。之所以转成set,是因为map集合具备着键的唯一性,其实set集合就来自于map,set集合底层其实用的就是map的方法。
2、 Map集合的三种取出方式
(1)、取出map集合中所有元素的方式一: Set<Key> keySet()方法。
将Map集合中的所有键存入到Set集合中。因为Set集合具备迭代器,所以可以通过迭代方式取出所有的键,然后根据Map集合中的get方法获取每一个键所对应的值。
1 import java.util.*; 2 class KeySetDemo 3 { 4 public static void main(String[] args) 5 { 6 Map<Integer,String> map=new HashMap<Integer,String>(); 7 map.put(1,"王武"); 8 map.put(7,"孙琦"); 9 map.put(6,"李四"); 10 map.put(4,"赵四"); 11 map.put(2,"钱枫"); 12 //先获取map集合的所有键的Set集合,keySet(); 13 Set<Integer> keyset=map.keySet(); 14 //有了Set集合。就可以获取其迭代器。 15 for (Iterator<Integer> it=keyset.iterator();it.hasNext() ; ) 16 { 17 Integer key=it.next(); 18 //有了键可以通过map集合的get方法获取其对应的值。 19 String value=map.get(key); 20 System.out.println("key="+key+":::"+"value="+value); 21 } 22 } 23 }
(2)、取出map集合中所有元素的方式二:Set<Map.Entry<Key,Value>> entrySet()方法。
将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry. Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。为什么要定义在内部呢?
因为只有有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。而且该事物在直接访问Map集合中的元素。
接口 Map.Entry<K,V>中的方法:
1 import java.util.*; 2 class EntrySetDemo 3 { 4 public static void main(String[] args) 5 { 6 Map<Integer,String> map=new HashMap<Integer,String>(); 7 map.put(1,"王武"); 8 map.put(7,"孙琦"); 9 map.put(6,"李四"); 10 map.put(4,"赵四"); 11 map.put(2,"钱枫"); 12 //将Map集合中的映射关系(Map.Entry)取出。存入到Set集合中。 13 Set<Map.Entry<Integer,String>> entryset=map.entrySet(); 14 //用迭代器进行迭代Set集合 15 for (Iterator<Map.Entry<Integer,String>> it=entryset.iterator();it.hasNext() ; ) 16 { 17 //it.next()返回的是Map集合中的映射关系(Map.Entry<K,V>) 18 Map.Entry<Integer,String> en=it.next(); 19 //通过Map.Entry中的getKey()和getValue()取到Map集合键和值。 20 int key=en.getKey(); 21 String value=en.getValue(); 22 System.out.println("key="+key+":::"+"value="+value); 23 } 24 } 25 }
(3)、取出map集合中所有元素的方式三:Collection<Value> values();返回Collection集合,然后在用Iterator迭代器来取出元素
1 import java.util.*; 2 class ValuesDemo 3 { 4 public static void main(String[] args) 5 { 6 Map<Integer,String> map=new HashMap<Integer,String>(); 7 map.put(1,"王武"); 8 map.put(7,"孙琦"); 9 map.put(6,"李四"); 10 map.put(4,"赵四"); 11 map.put(2,"钱枫"); 12 //用values方法取到Map集合中的全部的值,存放到Collection中 13 Collection<String> value=map.values(); 14 //用迭代器进行迭代这个存放Map集合全部值的Collection集合 15 for (Iterator<String> it=value.iterator();it.hasNext() ; ) 16 { 17 System.out.println("value="+it.next()); 18 } 19 } 20 }
3、Map集合综合练习
(1)、需求:描述一个学生,学生属性:姓名,年龄。每一个学生都有对应的归属地。学生Student,地址String。注意:姓名和年龄相同的视为同一个学生。保证学生的唯一性。
1 import java.util.*; 2 class Student 3 { 4 private String name; 5 private int age; 6 Student(String name,int age){ 7 this.name=name; 8 this.age=age; 9 } 10 public void setName(String name){ 11 this.name=name; 12 } 13 public void setAge(int age){ 14 this.age=age; 15 } 16 public String getName(){ 17 return name; 18 } 19 public int getAge(){ 20 return age; 21 } 22 public String toString(){ 23 return "name="+name+"....."+"age="+age; 24 } 25 public int hashCode(){ 26 return name.hashCode()+age*37; 27 } 28 public boolean equals(Object obj){ 29 if(!(obj instanceof Student)) 30 throw new RuntimeException("类型转换异常"); 31 Student stu=(Student)obj; 32 return this.name.equals(stu.name)&&this.age==stu.age; 33 } 34 } 35 class HashMapDemo 36 { 37 public static void main(String[] args) 38 { 39 //将学生对象和学生的归属地通过键与值的形式存储到map集合中 40 Map<Student,String> map=new HashMap<Student,String>(); 41 map.put(new Student("张三",20),"北京"); 42 map.put(new Student("钱枫",21),"深圳"); 43 map.put(new Student("王武",19),"郑州"); 44 map.put(new Student("赵四",33),"香港"); 45 map.put(new Student("孙琦",29),"广州"); 46 map.put(new Student("钱枫",21),"上海"); 47 //第一种方式:keySet(); 48 for (Iterator<Student> it=map.keySet().iterator();it.hasNext() ; ) 49 { 50 Student stu=it.next(); 51 String address=map.get(stu); 52 System.out.println(stu+":::"+address); 53 } 54 //第二种取出方式 55 for (Iterator<Map.Entry<Student,String>> it=map.entrySet().iterator();it.hasNext() ; ) 56 { 57 Map.Entry<Student,String> me=it.next(); 58 Student stu=me.getKey(); 59 String address=me.getValue(); 60 System.out.println(stu+":::"+address); 61 } 62 } 63 }
(2)、需求:对学生对象的年龄进行升序排序。因为数据是以键值对形式存在的。所以要使用可以排序的Map集合中TreeMap集合。
1 import java.util.*; 2 class Student implements Comparable<Student> 3 { 4 private String name; 5 private int age; 6 Student(String name,int age){ 7 this.name=name; 8 this.age=age; 9 } 10 public void setName(String name){ 11 this.name=name; 12 } 13 public void setAge(int age){ 14 this.age=age; 15 } 16 public String getName(){ 17 return name; 18 } 19 public int getAge(){ 20 return age; 21 } 22 public String toString(){ 23 return "name="+name+"....."+"age="+age; 24 } 25 public int compareTo(Student stu){ 26 int num=this.age-stu.age;//按年龄排序 27 if(num==0) 28 return this.name.compareTo(stu.name);//按姓名排序 29 return num; 30 } 31 /* 32 因为写的Student类,使用者有可能存放到HashMap集合中。 33 所以有必要复写hashCode方法和equals方法。 34 而且即使你不写,这两个方法都会存在Student类中,因为Object类中有这两个方法 35 public int hashCode(){ 36 return name.hashCode()+age*37; 37 } 38 public boolean equals(Object obj){ 39 if(!(obj instanceof Student)) 40 throw new RuntimeException("类型转换异常"); 41 Student stu=(Student)obj; 42 return this.name.equals(stu.name)&&this.age==stu.age; 43 } 44 */ 45 } 46 class StuComparator implements Comparator<Student> 47 { 48 public int compare(Student s1,Student s2){ 49 int num=s1.getAge()-s2.getAge(); 50 return (num==0)?s1.getName().compareTo(s2.getName()):num; 51 } 52 } 53 class TreeMapDemo 54 { 55 public static void main(String[] args) 56 { 57 TreeMap<Student,String> tm=new TreeMap<Student,String>(new StuComparator()); 58 tm.put(new Student("张三",20),"北京"); 59 tm.put(new Student("钱枫",21),"深圳"); 60 tm.put(new Student("王武",19),"郑州"); 61 tm.put(new Student("赵四",33),"香港"); 62 tm.put(new Student("孙琦",29),"广州"); 63 tm.put(new Student("钱枫",21),"武汉"); 64 tm.put(new Student("王武",19),"上海");//键相同值就会覆盖原来的键的值 65 Set<Map.Entry<Student,String>> entryset=tm.entrySet(); 66 for (Iterator<Map.Entry<Student,String>> it=entryset.iterator();it.hasNext() ; ) 67 { 68 Map.Entry<Student,String> en=it.next(); 69 Student stu=en.getKey(); 70 String address=en.getValue(); 71 System.out.println(stu+":::"+address); 72 } 73 } 74 }
(3)、需求: 使用LinkedHashMap则是跟原来存入的顺序是一致的。
1 import java.util.*; 2 class LinkedHashMapDemo 3 { 4 public static void main(String[] args) 5 { 6 LinkedHashMap<Integer,String> lhm=new LinkedHashMap<Integer,String>(); 7 lhm.put(1,"王武"); 8 lhm.put(7,"孙琦"); 9 lhm.put(6,"李四"); 10 lhm.put(4,"赵四"); 11 lhm.put(2,"钱枫"); 12 lhm.put(2,"黑马");//覆盖原来相同键的值 13 Set<Map.Entry<Integer,String>> entryset=lhm.entrySet(); 14 for (Iterator<Map.Entry<Integer,String>> it=entryset.iterator();it.hasNext() ; ) 15 { 16 Map.Entry<Integer,String> en=it.next(); 17 Integer key=en.getKey(); 18 String value=en.getValue(); 19 System.out.println(key+":::"+value); 20 } 21 } 22 }
运行结果:
(4)、需求:"sdfgzxcvas--==,.?dfxcvdf"获取该字符串中的字母出现的次数。希望打印结果:a(1)c(2).....
通过结果发现,每一个字母都有对应的次数。说明字母和次数之间都有映射关系。注意了,当发现有映射关系时,可以选择Map集合。因为Map集合中存放就是映射关系。
什么使用Map集合呢?
当数据之间存在这映射关系时,就要先想Map集合。
思路:
1,将字符串转换成字符数组。因为要对每一个字母进行操作。
2,定义一个Map集合,因为打印结果的字母有顺序,所以使用Treemap集合。
3,遍历字符数组。将每一个字母作为键去查Map集合。如果返回null,将该字母和1存入到Map集合中。
如果返回不是null,说明该字母在Map集合已经存在并有对应次数。 那么就获取该次数并进行自增,然后将该字母和自增后的次数存入到Map集合中。覆盖掉原来键所对应的值。
4,将Map集合中的数据变成指定的字符串形式返回。
1 //"sdfgzxcvas--==,.?dfxcvdf"获取该字符串中的字母出现的次数。希望打印结果:a(1)c(2)..... 2 import java.util.*; 3 class TreeMapTest 4 { 5 public static void main(String[] args) 6 { 7 String str="sdfgzxcvas--==,.?dfxcvdf"; 8 str=getCharCount(str); 9 System.out.println(str); 10 } 11 public static String getCharCount(String str){ 12 TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>(); 13 //把字符串转换成字符数组 14 char[] arr=str.toCharArray(); 15 for (int x=0;x<arr.length ;x++ ) 16 { 17 //程序健壮性的判断,如果是除了字母以外的字符直接过滤掉 18 if(!((arr[x]>='a'&& arr[x]>='z') || (arr[x]>='A'&& arr[x]>='Z'))) 19 continue; 20 //将数组中的字母作为键去查map表中的值 21 Integer value=tm.get(arr[x]); 22 int count=0; 23 //判断值是否为null,如果不为空记录这个值 24 if(value!=null) 25 count=value; 26 //如果不为空,count加1存进集合中,如果count=0,也加1存进去 27 count++; 28 tm.put(arr[x],count); 29 /* 30 if(value==null) 31 tm.put(arr[x],1); 32 else{ 33 value=value+1; 34 tm.put(arr[x],value); 35 } 36 */ 37 } 38 //创建字符串缓冲区用来修改成固定的字符串格式。 39 StringBuilder sb=new StringBuilder(); 40 for (Iterator<Map.Entry<Character,Integer>> it=tm.entrySet().iterator();it.hasNext() ; ) 41 { 42 Map.Entry<Character,Integer> en=it.next(); 43 Character key=en.getKey(); 44 Integer value=en.getValue(); 45 sb.append(key+"("+value+")"); 46 } 47 return sb.toString(); 48 } 49 }
(5)、Map集合扩展
在很多项目中,应用比较多的是一对多的映射关系,这就可以通过嵌套的形式将多个映射定义到一个大的集合中,并将大的集合分级处理,形成一个体系。
1 import java.util.*; 2 class Student 3 { 4 private String id; 5 private String name; 6 Student(String id,String name) 7 { 8 this.id = id; 9 this.name = name; 10 } 11 public String toString() 12 { 13 return id+":::"+name; 14 } 15 } 16 class MapDemo3 17 { 18 public static void demo() 19 { 20 HashMap<String,List<Student>> czbk = new HashMap<String,List<Student>>(); 21 List<Student> reyu = new ArrayList<Student>(); 22 List<Student> jiuye = new ArrayList<Student>(); 23 czbk.put("yureban",reyu); 24 czbk.put("jiuyeban",jiuye); 25 reyu.add(new Student("01","zhagnsa")); 26 reyu.add(new Student("04","wangwu")); 27 jiuye.add(new Student("01","zhouqi")); 28 jiuye.add(new Student("02","zhaoli")); 29 Iterator<String> it = czbk.keySet().iterator(); 30 while(it.hasNext()) 31 { 32 String roomName = it.next(); 33 List<Student> room = czbk.get(roomName); 34 System.out.println(roomName); 35 getInfos(room); 36 } 37 } 38 public static void getInfos(List<Student> list) 39 { 40 Iterator<Student> it = list.iterator(); 41 while(it.hasNext()) 42 { 43 Student s = it.next(); 44 System.out.println(s); 45 } 46 } 47 public static void main(String[] args) 48 { 49 demo(); 50 } 51 public static void getStudentInfo(HashMap<String,String> roomMap) 52 { 53 Iterator<String> it = roomMap.keySet().iterator(); 54 while(it.hasNext()) 55 { 56 String id = it.next(); 57 String name = roomMap.get(id); 58 System.out.println(id+":"+name); 59 } 60 } 61 }
(6)、 Map在有映射关系时,可以优先考虑,在查表法中的应用较为多见。
1 import java.util.*; 2 class MapTest1 3 { 4 public static void main(String[] args) 5 { 6 System.out.println(getWeek(1)); 7 } 8 public static String getWeek(int num){ 9 if(num<1 || num>7) 10 throw new RuntimeException("没有这个星期,请重新输入"); 11 String[] weeks={"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"}; 12 String s=weeks[num]; 13 TreeMap<String,String> tm=new TreeMap<String,String>(); 14 tm.put("星期一","Mon"); 15 tm.put("星期二","Tue"); 16 tm.put("星期三","Wes"); 17 tm.put("星期四","Sta"); 18 tm.put("星期五","Wek"); 19 tm.put("星期六","Sun"); 20 tm.put("星期日","Sun"); 21 return tm.get(s); 22 } 23 }
总结:
使用集合的技巧:
(1)、看到Array就是数组结构,有角标,查询速度很快。
(2)、看到Link就是链表结构:增删速度快,而且有特有方法。addFirst; addLast; removeFirst(); removeLast(); getFirst();getLast();
(3)、看到Hash就是哈希表,就要想要哈希值,就要想到唯一性,就要想到存入到该结构的中的元素必须覆盖hashCode,equals方法。
(4)、看到Tree就是二叉树,就要想到排序,就想要用到比较。
比较的两种方式:
一个是Comparable:覆盖compareTo方法;
一个是Comparator:覆盖compare方法。
LinkedHashSet,LinkedHashMap:这两个集合可以保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。
集合什么时候用?
当存储的是一个元素时,就用Collection。当存储对象之间存在着映射关系时,就使用Map集合。 保证唯一,就用Set。不保证唯一,就用List。
Collections:集合框架的工具类。里面定义的都是静态方法。
1、Collection和Collections有什么区别?
Collection是集合框架的一个顶层接口,它里面定义了单列集合的共性方法。它有两个常用的子接口:List对元素都有定义索引,是有序的,可以重复元素;Set不可以重复元素,无序的。
Collections是集合框架中的一个工具类。该类中的方法都是静态的,提供的方法中有可以对List集合进行排序、二分查找等方法。
2、Collections中的常用静态方法
(1)、对List集合进行排序
1 Collections.sort(List<T> list);//List集合进行元素的自然顺序排序 2 Collections.sort(List<T> list,Comparator<?super T> c);//按指定的比较器方法排序
(2)、对List集合进行二分查找
1 int Collections.binarySearch(List list, T key);//对List集合进行二分查找,返回角标。 2 int Collections.binarySearch(List list,T key,Comparator<T> c);//传入自定义的比较器进行查找
(3)、对List集合中的对象进行置换
1 Collections.swap(List list,int i,int j);// 在指定集合的指定位置处交换元素
(4)、fill方法可以将list集合中所有元素替换成指定元素。
1 Collections.fill(List<T> list, T obj);//使用指定元素替换指定集合中的所有元素。
(5)、获取Collection集合中的最大元素
1 T Collections.max(Collection coll);//根据元素的自然顺序,返回最大元素 2 T Collections.max(Collection coll, Comparator<T> comp);//根据指定比较器产生的顺序,返回最大元素。
(6)、List集合中新值替换老值
1 Collections.replaceAll(List list, T oldValue,T newValue);// 使用另一个值替换列表中出现的所有某一指定值。
(7)、集合进行反转
1 Collections.reverse(List list);//反转指定集合中元素的顺序 2 Comparator<T> reverseOrder();//返回一个比较器,它强行逆转实现了 Comparable 接口的对象。 3 Comparator<T> reverseOrder(Comparator<T> comp);// 返回一个比较器,该比较器将强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。
(8)、使用指定的随机源对指定列表进行置换。
1 Collections.shuffle(List list);//使用默认随机对集合进行置换。 2 Collections.shuffle(List list,Random rnd);//使用默认随机对集合进行置换
(9)、不同步的集合转成同步的集合。
//原理:定义一个类,将集合所有的方法加同一把锁后返回。 Collection Collections.synchronizedCollection(Collection coll); List Collections.synchronizedList(List list); Set Collections.synchronizedSet(Set set); Map Collections.synchronizedMap(Map);
代码演示:
(1)、
1 import java.util.*; 2 class CollectionsDemo 3 { 4 public static void main(String[] args) 5 { 6 List<String> list = new ArrayList<String>(); 7 list.add( "abcde"); 8 list.add( "cbad"); 9 list.add( "bb"); 10 list.add( "zzz"); 11 list.add( "cba"); 12 list.add( "a"); 13 sort(list); 14 binarySearch(list); 15 swap(list); 16 fill(list); 17 max(list); 18 replaceAll(list); 19 reverse(list); 20 shuffle(list); 21 } 22 //对List集合进行默认排序,因为TreeSet和TreeMap都能排序了 23 public static void sort(List<String> list){ 24 //List集合默认排序 25 Collections.sort(list); 26 sop(list);//运行结果:[a, abcde, bb, cba, cbad, zzz] 27 28 //指定比较器,按照比较器的比较方式进行比较 29 Collections.sort(list,new StringLenComp()); 30 sop(list);//运行结果:[a, bb, cba, zzz, cbad, abcde] 31 } 32 33 //二分查找 34 public static void binarySearch(List<String> list){ 35 //二分查找在查找之前必须根据元素的自然顺序对集合进行升序排序。 36 //如果没有对列表进行排序,则结果是不确定的。 37 //如果列表包含多个等于指定对象的元素,则无法保证找到的是哪一个。 38 Collections.sort(list); 39 sop(list);//[a, abcde, bb, cba, cbad, zzz] 40 int index=Collections.binarySearch(list,"bb"); 41 sop("index="+index);//index=2 42 43 //指定比较器进行二分查找 44 int num=Collections.binarySearch(list,"bb",new StringLenComp()); 45 sop(list);//运行结果:[abcde, cbad, bb, zzz, cba, a] 46 sop("index="+num);//运行结果:index=2 47 48 } 49 50 //对List集合中的对象进行置换 51 public static void swap(List<String> list){ 52 sop(list);//运行结果:[abcde, cbad, bb, zzz, cba, a] 53 Collections.swap(list,4,2); 54 sop(list);//运行结果:[abcde, cbad, cba, zzz, bb, a] 55 } 56 57 //fill方法可以将list集合中所有元素替换成指定元素。 58 public static void fill(List<String> list){ 59 sop(list);//运行结果:[abcde, cbad, bb, zzz, cba, a] 60 Collections.fill(list,"我爱黑马"); 61 sop(list);//运行结果:[我爱黑马, 我爱黑马, 我爱黑马, 我爱黑马, 我爱黑马, 我爱黑马] 62 } 63 64 //获取Collection集合中的最大元素 65 public static void max(List<String> list){ 66 String str=Collections.max(list); 67 sop(str);//运行结果:zzz 68 69 String s=Collections.max(list,new StringLenComp()); 70 sop(s);//运行结果:abcde 71 } 72 73 //List集合中新值替换老值 74 public static void replaceAll(List<String> list){ 75 sop(list);//运行结果:[abcde, cbad, bb, zzz, cba, a] 76 Collections.replaceAll(list,"cba","我要去黑马"); 77 sop(list);//运行结果:[abcde, cbad, bb, zzz, 我要去黑马, a] 78 } 79 80 //对集合进行反转 81 public static void reverse(List<String> list){ 82 sop(list);//运行结果:[abcde, cbad, bb, zzz, cba, a] 83 Collections.reverse(list); 84 sop(list);//运行结果:[a, cba, zzz, bb, cbad, abcde] 85 86 87 } 88 89 //使用指定的随机源对指定列表进行置换。 90 public static void shuffle(List<String> list){ 91 sop(list); 92 Collections.shuffle(list); 93 sop(list); 94 } 95 public static void sop(Object obj){ 96 System.out.println(obj); 97 } 98 } 99 class StringLenComp implements Comparator<String> 100 { 101 public int compare(String s1,String s2){ 102 int num=s1.length()-s2.length(); 103 if(num==0) 104 return s1.compareTo(s2); 105 return num; 106 } 107 }
(2)、
1 import java.util.*; 2 class ReverseOrderDemo 3 { 4 public static void main(String[] args) 5 { 6 //返回一个比较器,它强行逆转实现了 Comparable 接口的对象。 7 TreeSet<String> ts=new TreeSet<String>(Collections.reverseOrder()); 8 ts.add( "abcde"); 9 ts.add( "cbad"); 10 ts.add( "bb"); 11 ts.add( "zzz"); 12 ts.add( "cba"); 13 ts.add( "a"); 14 System.out.println(ts);//运行结果:[zzz, cbad, cba, bb, abcde, a] 15 16 //对集合进行了两次的反转就又变成了自然排序的顺序了 17 ts=new TreeSet<String>(Collections.reverseOrder(Collections.reverseOrder())); 18 ts.add( "abcde"); 19 ts.add( "cbad"); 20 ts.add( "bb"); 21 ts.add( "zzz"); 22 ts.add( "cba"); 23 ts.add( "a"); 24 System.out.println(ts);//运行结果:[a, abcde, bb, cba, cbad, zzz] 25 } 26 }
此类包含用来操作数组(比如排序和搜索)的各种方法。里面都是静态的方法。
(1)、数组按照升序进行排序
1 Arrays.sort(基本数据类型[]或者 对象[]);
2 eg:Arrays.sort(int[] arr);// 对指定的 int 型数组按数字升序进行排序。
(2)、数组进行二分查找
1 int Arrays.binarySearch(基本数据类型[] 或者 对象[],key); 2 eg: Arrays.binarySearch(int[] arr,int key);
(3)、将数组转换成集合
1 List asList(T...a);//T...a可变长度的数组
2 eg:String[] arr = {"abc","kk","qq"};
3 List<String> list = Arrays.asList(arr);//将arr数组转成list集合。
将数组转换成集合,有什么好处呢?用aslist方法,将数组变成集合。
可以通过List集合中的方法来操作数组中的元素:isEmpty()、contains、indexOf、set;
注意(局限性):数组是固定长度,不可以使用集合对象增加或者删除等,会改变数组长度的功能方法。比如add、remove、clear。(会报不支持操作异常UnsupportedOperationException);
如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。
如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
1 import java.util.*; 2 class ArraysDemo 3 { 4 public static void main(String[] args){ 5 int[] arr1 = {31,11,51,61}; 6 List< int[]> list1 = Arrays.asList(arr1); 7 System.out.println(list1);//运行结果:[[I@659e0bfd] 8 Integer[] arr2 = {31,11,51,61}; 9 List list2 = Arrays.asList(arr2); 10 System.out.println(list2);//运行结果:[31, 11, 51, 61] 11 } 12 }
(4)、将数组内容变成字符串打印出去
1 String Arrays.toString(基本数据类型[] 或者 对象[]);
代码演示:
1 import java.util.*; 2 class ArraysDemo 3 { 4 public static void main(String[] args){ 5 int[] arr={34,54,2,5,7,8}; 6 char[] ch={'a','g','j','h','l'}; 7 double[] dou={7.45,0.15,45.12,45,1256,4}; 8 byte[] by={0,1,5,3,5,0}; 9 String[] str={"nihao","hah","heihei"}; 10 System.out.println(Arrays.toString(arr));//运行结果:[34, 54, 2, 5, 7, 8] 11 System.out.println(Arrays.toString(ch));//运行结果:[a, g, j, h, l] 12 System.out.println(Arrays.toString(dou));//运行结果:[7.45, 0.15, 45.12, 45.0, 1256.0, 4.0] 13 System.out.println(Arrays.toString(by));//运行结果:[0, 1, 5, 3, 5, 0] 14 System.out.println(Arrays.toString(str));//运行结果:[nihao, hah, heihei] 15 } 16 }
使用的就是Collection接口中的toArray方法。
1 Object[] toArray(); 2 T[] toArray(T[] a);//返回数组的运行时类型与指定数组的运行时类型相同
集合转成数组,可以对集合中的元素操作的方法进行限定,不允许对其进行增删。只要获取这些元素即可。 toArray方法需要传入一个指定类型的数组,那么长度该如何定义呢?
当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。
当指定类型的数组长度大于了集合的size,就不会新创建了数组,而是使用传递进来的数组。
所以建议,在传递指定类型数组时,最好的方式就是指定的长度和size相等的数组。
1 import java.util.*; 2 class ArraysDemo 3 { 4 public static void main(String[] args){ 5 List<Integer> list=new ArrayList<Integer>(); 6 list.add(5); 7 list.add(4); 8 list.add(10); 9 list.add(12); 10 list.add(54); 11 Integer[] arr=list.toArray(new Integer[list.size()]);//刚刚好的数组长度 12 for (int x=0;x<arr.length ;x++ ) 13 { 14 System.out.println(arr[x]); 15 } 16 } 17 }
未完待续.............
注:菜鸟日记,如有错误欢迎大神指正,欢迎探讨!!
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------