第八章 集合
·集合简介:集合是一个类,集合大致可分为3中体系set(无序,不可重复的集合)、List(有序,重复的集合)、map(映射关系的集合)、Java5后加入Queue(队列集合)。集合中保存的数据是对象(其实平常所以的对象多指对象的引用)。
·集合概念:
集合跟数组类似。区别是数组元素可存储基本类型和对象类型,而集合中存储的值只能是对象(其实都是对象的引用变量),数组中存储的数据长度不可变,但集合中存储的对象数据多少可以随时添加与删除。
·集合中放置的都是Object类型,因此取出来的值也都是Object类型,所有最后取出来的值要强制转换成真正的类型(就是放进去是什么类型取出来还是什么类型)。
·MAP:map保存的是key --> value 对,map里的key不能重复。
·集合类位于java.util.* 下
Java集合:
常用集合类:Set(HashSet, TreeSet) List(ArrayList, LinkedList)
Map(HashMap, TreeMap)
·访问集合元素:
1、Set集合无序,所以只能根据元素本身来访问到它。
2、List集合有序,所以可以根据元素的索引来访问到它。
3、Map 映射,根据key来访问值。
·Collection和Iterator接口
·通过上图可以看出,Collection是Set,queue和List的父接口。
Collection集合方法:
booleanadd(Object o) :向集合中添加元素,如果添加成功则返回true。
booleanaddAll(Collection c) :该方法把指定集合中的所有元素添加到指定集合,如果成功返回true。
voidclear() :清除集合中的所有元素,集合长度变为0。
booleancontains(Object o) :返回集合中是否包含元素o。
booleancontainsAll(Collection o) :返回集合里是否包含集合o的所有元素。
booleanisEmpty() :判断集合是否为Null,如果集合为空返回ture,否则返回false。
Iteratoriterator() :返回一个Iterator类型的对象,用于便利集合里的元素。
booleanremove(Object o) :删除集合中指定的元素o,不管有多少个o,然后才返回true。
booleanremoveAll(Collection o) :从集合中删除包含o集合的所有元素,删除完之后返回true。
booleanretainAll(Collection o) :从集合中删除集合o不包含的元素,然后返回true。
intsize() :该方法返回集合元素的个数。
Object[]toArray() :把集合转换为一个数组。所有集合元素变成对应的数组元素。
·Iterator:为集合的迭代器,用来迭代集合的所有元素。所有集合都实现了Iterator接口的iterator方法。
·Iterator接口方法:
1、 booleanhasNext() :如果集合中还有下一个元素则返回true,用在for while循环的条件判断中。
2、 Object next() :返回集合中的下一个元素。
3、 void remove() :删除集合中上一次next()返回的元素。
·遍历集合:Iterator,while,增强for遍历集合。
例子:
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
public class IteratorTest
{
public static void main(String[] args)
{
Collection c = new HashSet();
c.add("a");
c.add("b");
c.add("c");
Iterator it = c.iterator();
//使用while语句与iterator
while(it.hasNext())
{
String sit = (String)it.next();
System.out.println(sit);
}
System.out.println("-----------------");
//使用for与iterator
for(Iterator itfor = c.iterator(); itfor.hasNext();)
{
String sitfor = (String)itfor.next();
System.out.println(sitfor);
}
System.out.println("--------------------");
//使用foreach语法
for(Object s : c)
{
String sfor = (String)s;
System.out.println(sfor);
}
}
}
·Set
·Set接口与 collection接口基本上完全一样,set没有提供任何额外方法,Set不允许包含重复元素。Set 常用的包含HashSet与TreeSet。HashSet底层是有HashMap实现的。
·HashSet:
特点:
1、无序。
2、不允许相同值添加到集合中。
·存储原理:存入一个元素时调用该对象的hashCode()方法获得hashCode值,根据HashCode值决定该对象存储的位置,所以存储与读取该元素时会很快,一下就能定位到元素的位置.
·HashSet底层是使用HashMap实现的。当使用add方法将对象添加到Set集合中时,实际上是Map对象的key,而Map key对应的value我们没有用到。
·HashSet判断重复元素有两个条件:
使用equal判断两个对象是否为true并且两个对象的hashcode值相同,则判定为同一个对象就不能添加进集合,否则如果不能同时满足两个条件就能将元素添加进集合。
出现的情况:
1、hashCode值相同equal相同则为同一对象,不会存入集合。
2、hashCode值相同equal值false,可以存入集合。保存在相同位置,用链式结构保存多个对象。因为HashSet通过hashCode值定位元素位置,如果hashcode值相同那么会影响性能。
3、hashCode值不同equal值true,可以存入集合。存到了不同的位置。
4、hashCode值不同equal值false,可以存入集合。存到不同位置。实际当中,当元素的hashCode值相同时,equal值一定要保持为true。如果重新hashCode,那么一定要对应的重写equal。
·LinkedHashSet
LinkedHashSet存储位置也是由hashCode值来决定的,但是他使用链表来维护元素的次序,遍历LinkedHashSet时,HashSet会以存入的次序取出元素。
·TreeSet
·Set集合无序但是TreeSet是有序的,TreeSet使元素值处于排序状态(由小到大)。TreeSet实现SortedSet接口。
·Set元素不能重复TreeSet也一样,TreeSet判断是不是同一个元素:通过equals比较返回true,并且通过compareTo方法或compare比较返回0
·TreeSet比其他Set多了几个方法:
Comparatorcomparator() :返回对此 set 中的元素进行排序的比较器;如果此 set 使用其元素的自然顺序,则返回null
Object first() :返回Set中第一个元素(最小的)。
Object last() :返回Set中最大的一个元素。
Object lower(Object e) : 返回Set中小于e的元素。
Object higher(Object e) :返回Set中大于e的元素。
SortedSet subSet(fromElement,toElement) :返回Set中fromElement(包含本身)到toElement(不包含本身)的元素。
SortedSet headset(toElement) : 返回toElement前面的元素。
SortedSet tailSet(fromElement) : 返回fromElement后面的元素。
例子a:
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add(-1);
ts.add(-3);
ts.add(12);
ts.add(1);
System.out.println(ts);
System.out.println(ts.first());
System.out.println(ts.last());
System.out.println(ts.subSet(1,12));
}
}
·TreeSet支持两种排序算法,自然排序和定制排序:
·自然排序:就是升序。
·Comparable接口中包含compareTo(Objectobj)方法,实现该接口类的对象就可以比较大小,比如:a.compareTo(b) 返回负数表示对象a小于对象b,返回0表示a与b相当,返回正数表示a大于b。一些常用类已经实现了该接口的该方法,如:Ingeger数字类,Dage日期类,String字符类,Charater类,Boolean类。
·Comparator接口包含compare(To1, T o2)方法也叫比较器,例如TreeSet类有一个构造器接受Comparator的比较器,比较器是自己定义的比较大小的规则,当compare方法返回负数时表示o1对象小于o2对象,返回0时表示o1与o2相等,返回正数时表示o1大于o2。compare用在自定义的类中需要自己定义排序规则如正序倒序等,比如自己创建一个类类中创建TreeSet集合,此时就能定义一个排序规则的类,然后将这个类的compare比较器传给TreeSet接受Comparator类型参数的构造器就好了,后面有一个例子。
自然排序列子:
上面例子a就是自然排序。因为Integer类实现了compareTo接口都是按照自然排序来的。
自定义排序:
反排序:
import java.util.*;
public class TreeSetTest3
{
public static void main(String[] args)
{
TreeSet s = new TreeSet(new MyComparator()); //因为集合是带泛型声明的,这里没有赋予泛型实参,所以默认就是Object类型的。
s.add("A"); //这里面的类型是Object的子类
s.add("C");
s.add("B");
for(Object si : s) //这里的si和s都是Object类型的,并不是String类型的
{
String sic = (String)si; //所以这里需要进行强制类型转换
System.out.println(sic); //这样才能输出正确的结果,不然会报错类型错误
}
}
}
class MyComparator implements Comparator //TreeSet构造器传入的Comparator类,实现compare方法
{
public int compare(Object a, Object b)
{
String a1 = (String)a;
String b1 = (String)b;
return b1.compareTo(a1); //这里是String类的Comparable接口的compareTo方法。这里b1比a1就是反排序,a1比b1就是自然排序了。
}
}
·如果用自定义的类型的数据的话,那么不能比较两个对象类型的大小,因为自定义类型没有实现compara方法,可以自行实现一个compara比较器后就能进行自定义排序了,否则没有比较器会报错的。