java集合框架是初次可以接触到数据结构知识的一部分人内容,所以很重要,可是理解起来也不是那么的容易。
java集合中connection下面有三个子类:set,list,map。因为是子类所以大多都继承了connection类的方法,在此方法就不一一列举了,有兴趣的可以自己去查看java8 API。
那么下面主要来介绍一下三个子类各自的特点以及区别吧。Set是一个集合,所以不允许有重复的元素,又因为是无规则存放,所以是没有顺序的,即便是先放进去的也不一定会首先或者最后出来。set集合有个最重要的子类,就是hashset,因为很多情况都要重写equals方法以及hashcode方法,因为根据hashcode这一方式可以很快的找到元素。我有一篇文章,专门介绍了java重写equals方法以及hashcode的方法。
下面来举一个例子
package java8;
import java.util.HashSet;
class A{
public boolean equals(Object obj){
return false;
}
}
class B{
public int hashCode(){
return 1;
}
}
class C{
public boolean equals(Object obj) {
return true;
}
public int hashCode() {
return 2;
}
}
public class HashSetTest {
public static void main(String[] args){
HashSet books=new HashSet();
books.add(new A());
books.add(new A());
books.add(new B());
books.add(new B());
books.add(new C());
books.add(new C());
System.out.println(books);
}
}
[java8.B@1, java8.B@1, java8.C@2, java8.A@513e86ec, java8.A@29e07d3e]
这段代码主要通过重写了equals方法和hashcode方法来比较一下重写带来的影响,如果需要重写该对象对应类的equals方法,则也应该重写hashcode方法,规则是:如果两个对象通过equals()方法比较返回true,这两个对象的hashcode值也应该相同。
还有就是在hashset中添加可变对象时,如果修改了hashset集合中的对象,有可能导致该对象与集合中的其他对象相等,导致hashset无法准确访问该对象。
hashset还有一个子类linkedhashset,通过链表维护输入出顺序,,输出linkedhashset集合元素时总是,元素顺序总是与添加顺序一致。
其次还有一个用于排序的set集合,treeset是sortedset接口的实现类,总是处于排序状态,自然排序就是依照升序(依照红黑树算法),要是需要定制排序,那么就需要用到Comparator comparator();
package java8;
import java.util.Comparator;
import java.util.TreeSet;
import org.omg.CORBA.PUBLIC_MEMBER;
class M{
int age;
public M(int age){
this.age=age;
}
public String toString(){
return "M[age:"+age+"]";
}
}
public class TreeSetTest4 {
public static void main(String[] aegs) {
TreeSet tSet=new TreeSet(
new Comparator() {
public int compare(Object o1,Object o2){
M m1=(M)o1;
M m2=(M)o2;
return m1.age>m2.age?-1:m1.age<m2.age?1:0;
}
});
tSet.add(new M(5));
tSet.add(new M(0));
tSet.add(new M(-3));
tSet.add(new M(9));
System.out.println(tSet);
}
}
[M[age:9], M[age:5], M[age:0], M[age:-3]]
这段代码演示了定制排序的修改规则,就是通过comparator接口来改写。
还有就是改写equals方法时,最好一起修改compareTo()方法。
还有一个枚举类的set子类:enumSet,这是性能最好的集合类,并且按照定义顺序的方式来排序,所以也是有序的,不过枚举必须是同一个枚举类的枚举值,就像下面的程序一样
package java8
import java.util.EnumSet
enum Season{
SPRING,SUMMER,FALL,WINTER
}
public class EnumSetTest {
public static void main(String[] args) {
EnumSet es1=EnumSet.allOf(Season.class)
System.out.println(es1)
EnumSet en2=EnumSet.noneOf(Season.class)
System.out.println(en2)
en2.add(Season.WINTER)
en2.add(Season.SPRING)
}
}
[SPRING, SUMMER, FALL, WINTER]
[]
EnumSet集合类不允许加入null值,否则将会抛出nullpointerexception异常,其次要用类方法来创建对象。
**下面介绍一下List集合**
list可以使用connection集合中的所有方法,而且list集合是有序的,并且可以通过索引来查找元素:get()方法。对于set遍历一样,list也可以使用iterator(),来遍历,除此之外,它还提供了一个额外的listIterator()方法来遍历,它是子类所以拥有iterator的所有方法,在此之上,还添加了一些新的方法:
》boolean hasPrevious():返回该迭代器关联的集合是否还有上一个元素。
》object previous():返回该迭代器的上一个元素。
》void add(object o):指定位置插入新元素。
所以总结来说,就是增加了向前迭代的功能。下面用一段程序来解释这个方法:
package java8;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorTest {
public static void main(String[] args) {
String[] books={
"白夜行","解忧杂货店","嫌疑人X献身"
};
List<String> booklist=new ArrayList<>();
for(int i=0;i<books.length;i++)
booklist.add(books[i]);
ListIterator<String> ite=booklist.listIterator();
while(ite.hasNext()){
System.out.println(ite.next());
ite.add("------------------");
}
System.out.println("======下面开始迭代======");
while(ite.hasPrevious()){
System.out.println(ite.previous());
}
}
}
白夜行
解忧杂货店
嫌疑人X献身
白夜行
ArrayList和Vector作为List集合的两个典型实现,继承了List接口的所有方法,而且他们都是基于数组实现的,所以可以为其动态的,允许再分配内存,没有分配长度的时候,默认为10;要是指定长度,可以用initialCapability,其次还有两个方法来分配内存呢:
》void ensureCapability(int minCapability):将object[] 数组长度增加最少minCapability长度。
》void trimToSize():调整集合中的object[] 数组长度为当前元素的个数。
一般情况之下,最好用ArrayList,因为Vector有很多缺点,即便是线程安全的,也不要轻易使用vector,即便要用到Stack也不要用Vector,因为可以使用ArrayDeque。
**Map集合**
Map是保存具有映射关系的数据,主要就是保存着两组值,一组保存key,一组保存Value值,就是key-value关系的映射关系,其实就是set的一个另外的方式key值附带一个value,所以所有的方法都和Set方式一样,就连子类也是一样的,即便如此,也会在set基础上添加一些自己特有的方法,这我就不一一列举了,还是自己查看Api吧。
下面来通过一个题目来介绍,怎么得到key值吧。
a字符串数组的值如下:{"a","b","a","b","c","a","b","c","b"};,使用Map的key保存数组中的字符串元素,value保存该字符串出现次数,最后统计各字母出现的次数。
代码如下:
package java7lianxi;
import java.util.HashMap;
import java.util.Map;
public class MapTest2 {
public static void main(String[] args){
String a[]={"a","b","a","b","c","a","b","c","b"};
Map<String, Integer> gpp=new HashMap<>();
for(int i=0;i<a.length;i++){
if(gpp.get(a[i])==null)
{
gpp.put(a[i], 1);
}
else gpp.put(a[i], gpp.get(a[i])+1);
}
System.out.println(gpp);
}
}
{b=4, c=2, a=3}
下面的这个方法是来找到key值的,代码如下:
public class MapTest {
public Object getkey(Map map,int value){
for(Object key:map.keySet()){
if(map.get(key).equals(value))
return key;
}
return null;
}
还有通过EntrySet()方法找到key值:
Set entries = map.entrySet( );
if(entries != null) {
Iterator iterator = entries.iterator( );
while(iterator.hasNext( )) {
Map.Entry entry =iterator.next( );
Object key = entry.getKey( );
Object value = entry.getValue();
}
}
**这里不包括queue集合的使用,因为涉及到栈和队列的使用,我会单独拿出来说一下,比较难也很重要的部分就是双端队列和栈的相互转换**