JAVA基础-集合

来源:互联网 发布:苹果整合好了的ck源码 编辑:程序博客网 时间:2024/06/06 00:19
java集合框架:


Java集合分为:Set、List、Map三种体系。
Set:无序的,不可重复的;
List:有序的,可重复的;
Map:代表有映射关系的集合,Map保存的每一项数据都是key-value对。
Java 5后添加了Queue体系,代表一种队列集合实现。
Java集合由两个接口派生而出:Collection和Map,这两个是Java集合框架的根接口。
Collection接口:List接口、Set接口、Queue接口
Map接口:Hashmap实现类
Collection接口:
1.Collection 接口是List、Set、Queue接口的父接口,定义了如下操作集合元素的方法:
1.1 boolean add(Object o):向集合里添加一个元素,如果集合对象被添加操作改变则返回true;
1.2 boolean addAll(Collection c):将指定 collection 中的所有元素都添加到此 collection 中,如果集合对象被添加返回true;
1.3 void clear():移除此 collection 中的所有元素,将集合长度变为0;
1.4 boolean contains(Object o):如果此 collection 包含指定的元素,则返回 true。
1.5 boolean containsAll(Collection<?> c):如果此 collection 包含指定 collection 中的所有元素,则返回 true。
1.6 boolean equals(Object o):比较此 collection 与指定对象是否相等。
1.7 int hashCode():返回此 collection 的哈希码值。
1.8 boolean isEmpty():如果此 collection 不包含元素,则返回 true。
1.9 Iterator<E> iterator():返回一个Iterator对象,用于遍历集合里的元素;
1.10 boolean remove(Object o):从此 collection 中移除指定元素的单个实例,如果存在的话返回true;
1.11 boolean removeAll(Collection c):移除此 collection 中那些也包含在指定 collection 中的所有元素,如果存在的话返回true;
1.12 boolean retainAll(Collection c):仅保留此 collection 中那些也包含在指定 collection 的元素,如果存在的话返回true;
1.13 int size():返回此 collection 中的元素个数;
1.14 Object[] toArray():该方法把集合转换成一个数组,所有的集合元素变成对应的数组元素;
2.使用Iterator接口遍历集合元素
Iterator 主要用于遍历Collection集合中的元素,Iterator对象也被称为迭代器。
Iterator 仅用于遍历集合,必须依附于Collection对象。
使用 Iterator 对集合元素进行迭代时,并不是把集合元素本身传给迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对集合元素本身没有任何影响。
提供的方法:
1.boolean hasNext()如果仍有元素可以迭代,则返回 true。
2.Object next()返回迭代的下一个元素。
3.void remove()删除集合里上一次next方法返回的元素。
3.使用foreach循环遍历集合元素
          比起Iterator更加简洁,同样集合不能被改变。
4.Set 集合
无序的,不可重复,与Collection基本一样,无提供额外的方法。
4.1 HashSet 类:按hash算法存储集合中的元素,具有很好的存取和存取性能,具有以下特点:
1).不能保证元素的排列顺序,顺序可能和添加顺序不同,也可能发生改变。
2).HashSet不是同步的,多个线程同时对HashSet操作,必须通过代码保证其同步。
3).集合元素可以是null;
HashSet集合判断两个元素是否相等是同时通过equals()方法和两个对象的hashCode()方法返回值是否相等,
又因为set集合的规则是不能存在相同的元素,所以在重写该对象对应类的equals()方法,则也应该重写hashCode()方法。
          重写equals方法时需要重写hashCode方法,主要是针对Map、Set等集合类型的使用
          (关于==和equals的比较:
因为java所有类都继承于Object基类,而Object中equals用==来实现,所以equals和==是一样的,都是比较对象地址,java api里的类大部分都重写了equals方法,包括基本数据类型的封装类、String类等。对于String类==用于比较两个String对象的地址,equals则用于比较两个String对象的内容(值)。
String类重写了Object类的equlas方法,使得比较字符串内容是否相等可以直接使用equlas方法。
1.String a = "abc";时,JVM为了提高性能和减少内存开销,内部维护了一个字符串常量池,每当创建字符串常量时,JVM首先检查字符串常量池,如果常量池中已经存在,则返回池中的字符串对象引用,否则创建该字符串对象并放入池中。
2.String a = new String("abc");时。分两步 1、String object = "abc"; 2、String s = new String(object); 第一步参考第一种创建方式,而第二步由于"abc"已经被创建并保存到字符串常量池中,因此jvm只会在堆中新创建一个String对象去指向常量池中的abc。
intern()方法返回字符串对象在字符串常量池中的对象引用(new时创建的),若字符串常量池中尚未有此字符串,则创建一新的字符串常量放置于池中。
http://www.cnblogs.com/lwbqqyumidi/p/4060845.html(注意最后的反射修改字符串方法)
          )
hashCode()方法重写的基本规则
1).程序运行过程中,同一个对象多次调用hashCode()方法应该返回相同的值;
2).当两个对象通过equals()方法比较返回true时,两个对象的hashCode()方法应返回相等值;
3).对象中用作equals()方法比较的标准field,都应该用计算hashCode值。
4.2 LinkedHashSet 类
LinkedHashSet集合也是更加hashCode值来决定元素的存储位置,但他可以保存元素插入的顺序,
也因为要维护元素的插入顺序,因此性能略低于HashSet的性能,但是迭代访问所有元素时有很好的性能。
LinkedHashSet 同样不能出现相同的元素,因为它依然是HashSet.
4.3 TreeSet 类
TreeSet可以确保集合元素处于排序状态(元素有序),它除了提供HashSet有的方法外还提供了以下方法:
1).Comparator comparator():如果采用的是定制排序,返回所使用的Comparator;
如果采用自然排序,返回null。
2).Object first() 返回集合中的第一个元素
3).Object last() 返回集合中的最后一个元素
4).Object lower(Object e)返回集合中位于指定元素之前的元素(既小于指定元素的最大元素,参考元素不需要是TreeSet集合里的元素)
5).Object higher(Object e)返回集合中位于指定元素之后的元素(既大于指定元素的最大元素,参考元素不需要是TreeSet集合里的元素)
6).SortedSet subSet(E fromElement, E toElement) )返回此Set的子集合,范围从fromElement(包含)到toElement(不包含)
7).SortedSet headSet(Object toElement)返回小于toElement小的set子集
8).SortedSet tailSet(Object fromElement)返回大于或者等于fromElement的Set子集
4.4 EnumSet 类
EnumSet是一个枚举类设计的集合类,EnumSet中的每个元素都必须是指定枚举类型的枚举值。
EnumSet的集合元素也是有序的,以枚举值在枚举类的定义顺序来决定集合元素的顺序。
EnumSet不允许加入null元素,否则会报错。EnumSet内部以单位向量存储,占用内存小,运行高效,尤其批量操作。
EnumSet提供了如下常用static方法创建对象:
1).allOf(Class<E> elementType)
     创建一个指定枚举类里所有包含枚举值的EnumSet集合
2).complementOf(EnumSet<E> s)
     创建一个其元素类型与指定枚举 set 相同的枚举 set,最初包含指定 set 中所不包含的此类型的所有元素。
3).copyOf(Collection<E> c)
     使用一个普通集合来创建EnumSet集合
4).copyOf(EnumSet<E> s)
     创建一个与指定EnumSet具有相同元素类型、相同集合元素的EnumSet集合
5).noneOf(Class<E> elementType)
     创建一个具有指定元素类型的空枚举 set。
6).of(E e1, E e2, E e3, E e4, E e5......)
     创建一个最初包含指定元素的枚举 set。
7).range(E from, E to)
     创建一个包含从frome枚举值到to枚举值方位内的所有枚举值的EunmSet集合
5 各Set实现类性能分析
HashSet 和 TreeSet ,HashSet的整体性能总比TreeSet好,特别是添加和查询操作,只有当一个保持排序的Set时才使用TreeSet。
LinkedHashSet 和 HashSet ,HashSet的插入和删除略快,但是LinkedHashSet的遍历会比HashSet更快。
EnumSet 是所有set中性能最好的,但它只鞥呢保存同一个枚举类的值作为集合。
set的三个实现类HashSet、TreeSet、EnumSet都是线程不安全的。多个线程访问或操作Set,必须手动保证该Set的同步性.
6.List
1)ArrayList:
ArrayList数组线性表的特点为:类似数组的形式进行存储,因此它的随机访问速度极快。
ArrayList数组线性表的缺点为:不适合于在线性表中间需要频繁进行插入和删除操作。因为每次插入和删除都需要移动数组中的元素。
可以这样理解ArrayList就是基于数组的一个线性表,只不过数组的长度可以动态改变而已。
a.如果在初始化ArrayList的时候没有指定初始化长度的话,默认的长度为10.
b.ArrayList在增加新元素的时候如果超过了原始的容量的话,ArrayList扩容ensureCapacity的方案为“原始容量*3/2+1"
c.ArrayList是线程不安全的,在多线程的情况下不要使用。如果一定在多线程使用List的,您可以使用Vector,因为Vector和ArrayList基本一致,区别在于Vector中的绝大部分方法都使用了同步关键字修饰,这样在多线程的情况下不会出现并发错误,还有就是它们的扩容方案不同,ArrayList是通过原始容量*3/2+1,而Vector是允许设置默认的增长长度,Vector的默认扩容方式为原来的2倍。切记Vector是ArrayList的多线程的一个替代品。
d.ArrayList实现遍历的几种方法:foreach、iterator迭代器、for循环
2)LinkedList
LinkedList的链式线性表的特点为: 适合于在链表中间需要频繁进行插入和删除操作。
LinkedList的链式线性表的缺点为: 随机访问速度较慢。查找一个元素需要从头开始一个一个的找。
可以这样理解LinkedList就是一种双向循环链表的链式线性表,只不过存储的结构使用的是链式表而已。
a.LinkedList和ArrayList的区别和联系
ArrayList数组线性表的特点为:类似数组的形式进行存储,因此它的随机访问速度极快。
ArrayList数组线性表的缺点为:不适合于在线性表中间需要频繁进行插入和删除操作。因为每次插入和删除都需要移动数组中的元素。
LinkedList的链式线性表的特点为:适合于在链表中间需要频繁进行插入和删除操作。
LinkedList的链式线性表的缺点为:随机访问速度较慢。查找一个元素需要从头开始一个一个的找。
b.LinkedList的内部实现:LinkedList的内部是基于双向循环链表的结构来实现的。在LinkedList中有一个类似于c语言中结构体的Entry内部类。在Entry的内部类中包含了前一个元素的地址引用和后一个元素的地址引用类似于c语言中指针。
c.LinkedList不是线程安全的:注意LinkedList和ArrayList一样也不是线程安全的,如果在对线程下面访问可以自己重写LinkedList,然后在需要同步的方法上面加上同步关键字synchronized。
d.LinkedList的遍历方法
e.LinkedList可以被当做堆栈来使用
     由于LinkedList实现了接口Dueue,所以LinkedList可以被当做堆栈来使用。
Map接口:
Map接口实现的是一组Key-Value的键值对的组合。 Map中的每个成员方法由一个关键字(key)和一个值(value)构成。Map接口不直接继承于Collection接口(需要注意啦),因为它包装的是一组成对的“键-值”对象的集合,而且在Map接口的集合中也不能有重复的key出现,因为每个键只能与一个成员元素相对应。在我们的日常的开发项目中,我们无时无刻不在使用着Map接口及其实现类。Map有两种比较常用的实现:HashMap和TreeMap等。HashMap也用到了哈希码的算法,以便快速查找一个键,TreeMap则是对键按序存放,因此它便有一些扩展的方法,比如firstKey(),lastKey()等,你还可以从TreeMap中指定一个范围以取得其子Map。键和值的关联很简单,用pub(Object key,Object value)方法即可将一个键与一个值对象相关联。用get(Object key)可得到与此key对象所对应的值对象。另外前边已经说明了,Set接口的底层是基于Map接口实现的。Set中存储的值,其实就是Map中的key,它们都是不允许重复的。
HashMap实现了Map、CloneMap、Serializable三个接口,并且继承自AbstractMap类。HashMap基于hash数组实现,若key的hash值相同则使用链表方式进行保存。新建一个HashMap时,默认的话会初始化一个大小为16,负载因子为0.75的空的HashMap,在HashMap中当数据量很多时,并且已经达到了负载限度时,会重新做一次哈希,也就是说会再散列。调用的方法为resize(),并且java默认传入的参数为2*table.length。HashMap中还存在一个内部类Entry,用于链表的存储,存储链表的下一节点。
Hashtable实现Map接口,继承自古老的Dictionary类,实现一个key-value的键值映射表。任何非空的(key-value)均可以放入其中。
HashMap与Hashtable的区别:
1.      Hashtable是基于陈旧的Dictionary实现的,而HashMap是基于Java1.2引进的Map接口实现的;
2.      Hashtable是线程安全的,而HashMap是非线程安全的,我们可以使用外部同步的方法解决这个问题。
3.      HashMap可以允许你在列表中放一个key值为null的元素,并且可以有任意多value为null,而Hashtable不允许键或者值为null。
HashMap可以通过下面的语句进行同步:Map m = Collections.synchronizeMap(hashMap);
结论:
Hashtable和HashMap有几个主要的不同:线程安全以及速度。仅在你需要完全的线程安全的时候使用Hashtable,而如果你使用Java 5或以上的话,请使用ConcurrentHashMap吧。
1.ArrayList初始大小10,扩容为原来的1.5倍+1,Vector扩容为原来的两倍。
2.HashMap初始大小16,扩容为原来的2倍。
3.ConcurrentHashMap中,采用分段锁,通过把整个Map分为N个Segment(类似HashTable),可以提供相同的线程安全,但是效率提升N倍,默认提升16倍,默认是把segments初始化为长度为16的数组。 

collections.sort升序降序:
java Collections.sort默认的是升序
例如:
比如原来你的comparator方法,返回的是
class A{int a;}
comparator(A a1,A a2){return a1.a-a2.a}//升序
comparator(A a1,A a2){return a2.a-a1.a}//降序

Collections.sort(positionArray, new Comparator<Integer>() {
@Override
public int compare(Integer lhs, Integer rhs) {
//降序
if(lhs > rhs){
     return -1;
}else if(lhs < rhs){
     return 1;
}else{
     return 0;
}
}
});
Collections.sort(positionArray, new Comparator<Integer>() {
@Override
public int compare(Integer lhs, Integer rhs) {
//升序
if(lhs > rhs){
     return 1;
}else if(lhs < rhs){
     return -1;
}else{
     return 0;
}
}
});

arraylist和Vector区别:
Vector和ArrayList基本一致,区别在于Vector中的绝大部分方法都使用了同步关键字修饰,这样在多线程的情况下不会出现并发错误,还有就是它们的扩容方案不同,ArrayList是通过原始容量*3/2+1,而Vector是允许设置默认的增长长度,Vector的默认扩容方式为原来的2倍。切记Vector是ArrayList的多线程的一个替代品。

HashMap和concurrenthashmap:
并发编程实践中,ConcurrentHashMap是一个经常被使用的数据结构,相比于Hashtable以及Collections.synchronizedMap(),ConcurrentHashMap在线程安全的基础上提供了更好的写并发能力,但同时降低了对读一致性的要求
是HashTable的替代,是线程安全的,比HashTable的扩展性更好。月hashmap的区别是:线程安全以及速度

hashmap死循环:
多线程并发操作hashmap的时候,resize时进行rehash过程中产生的

list去重:
              //----------------------------------------------1
//            sets.addAll(lists);
//            listsNew.addAll(sets);
              //----------------------------------------------2
//            for (Stringstr: lists) {
//                   if (sets.add(str)) {
//                         listsNew.add(str);
//                   }
//            }
              //----------------------------------------------3
//            for (Stringstr: lists) {
//                   if (!listsNew.contains(str)) {
//                         listsNew.add(str);
//                   }
//            }
              //----------------------------------------------4
//            List<String> listsNew2 = new ArrayList<String>(new HashSet<String>(lists));
              //----------------------------------------------5
//            List<String> listsNew2 = new ArrayList<String>(new TreeSet<String>(lists));
原创粉丝点击