集合框架(Collection Framework)泛指java.util包的若干个类和接口.如Collection,List,ArrayList,LinkedList,Vector(自动增长数组),HashSet,HashMap等.
集合框架中的类主要封装的是典型的数据结构,如动态数组,链表,堆栈,集合,哈希表等.
集合框架类似编程中经常用到的工具类,使得编码这专注于业务层的实现,不需要从底层实现相关细节—“数据结构的封装”和”典型算法的实现”.
1. Collection框架中实现比较要实现什么接口? Comparable/comparator
2. ArrayList和Vector的区别?
这两个类都实现了List接口,List接口继承了Collection接口,他们都是有序集合.即存储在这两个集合中的元素的位置都是由顺序的,相当于一种动态的数组,我们以后可以按位置索引号来取出某个元素,并且其中的数据是允许重复的.这是HashSet之类的集合的最大不同处,HashSet之类的集合不可以按索引号去检索其中的元素.也不允许有重复的元素.本题目本与hashset没有任何关系,但为了说清楚ArrayList和Vector的功能,我们使用对比方式,有利于说明问题.
接着才说ArrayList与Vector的区别,主要包括两个方面:
(1)同步性
Vector是线程安全的,也就是说它的方法之间线程同步.而ArrayList是先程序不安全的,它的方法之间的线程数不同步的,如果只有一个线程会访问到集合,那么最好用ArrayList,因为它不考虑线程安全,效率会高些.如果有多个线程会访问到集合,那么就使用Vector,因为不需要我们自己去考虑和编写线程安全代码.
备注:对于Vector和ArrayList,Hashtable和HashMap,线程安全是前2个,记住Vector和Hashtable是旧的,是java一诞生就提供了的,他们是线程安全的.而Arratlist和HashMap是java2才提供的,他们是线程不安全的.
(2)数据增长
ArrayList和Vector都有一个初始的容量大小,但存储进他们里面的元素的个数超过了容量时,就需要增加ArrayList和Vector的存储空间,每次要增加时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间里同和程序效率之间要取得一定的平衡.Vector增长为原来的一倍,ArrayList增加原来的0.5倍.
3. HshMap和Hashtable的区别?
HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,在只有一个线程访问的情况下,效率要高于Hashtable。
HashMap允许将null作为一个entry的key或者value,而Hashtable不允许.总之有三条:
一.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现
二.同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的
三.值:只有HashMap可以让你将空值作为一个表的条目的key或value
4. List和Map的区别?
一个是存储单列数据的集合,另一个是存储键和值这样的双列数据的集合,
List中存储的数据是有顺序,并且允许重复;Map中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的。
5、List, Set, Map是否继承自Collection接口?
List,Set是,Map不是
6.List、Map、Set三个接口,存取元素时,各有什么特点?
List 以特定次序来持有元素,可有重复元素。Set 无法拥有重复元素,内部排序。Map 保存key-value值,value可多值。
1. 说出ArrayList,Vector,LinkedList的存储性能和特性
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
LinkedList也是线程不安全的,LinkedList提供了一些方法,使得LinkedList可以被当作堆栈和队列来使用。
4、去掉一个Vector集合中重复的元素
Vector newVector =new Vector();
For (inti=0;i<vector.size();i++)
{
Object obj =vector.get(i);
if(!newVector.contains(obj);
newVector.add(obj);
}
还有一种简单的方式,HashSet set = new HashSet(vector);
9、Collection和 Collections的区别。
Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
10.Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?
Set里的元素是不能重复的,元素重复与否是使用equals()方法进行判断的。
equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。
11.你所知道的集合类都有哪些?主要方法?
最常用的集合类是List 和 Map。 List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。 List 适用于按数值索引访问元素的情形。
Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。
ArrayList/VectoràList
àCollection
HashSet/TreeSetàSet
PropetiesàHashTable
àMap
Treemap/HashMap
对于set,大概的方法是add,remove, contains;对于map,大概的方法就是put,remove,contains等,因为,我只要在eclispe下按点操作符,很自然的这些方法就出来了。我记住的一些思想就是List类会有get(int index)这样的方法,因为它可以按顺序取元素,而set类中没有get(int index)这样的方法。List和set都可以迭代出所有元素,迭代时先要得到一个iterator对象,所以,set和list类都有一个iterator方法,用于返回那个iterator对象。map可以返回三个集合,一个是返回所有的key的集合,另外一个返回的是所有value的集合,再一个返回的key和value组合成的EntrySet对象的集合,map也有get方法,参数是key,返回值是key对应的value。
12、两个对象值相同(x.equals(y)== true),但却可有不同的hashcode,这句话对不对?
对。
如果对象要保存在HashSet或HashMap中,它们的equals相等,那么,它们的hashcode值就必须相等。
如果不是要保存在HashSet或HashMap,则与hashcode没有什么关系了,这时候hashcode不等是可以的,例如arrayList存储的对象就不用实现hashcode,当然,我们没有理由不实现,通常都会去实现的。
值相同决定不了hashcode相同;但hashcode相同则可以决定值相同。
hashcode决定的是两者是不是同一个对象,值可以简单理解为对象的值;如果hashcode算法完善无缺,那么它相同则值就一定相同,因为两者就是同一个对象,值能不相同么? hashcode不同,则说明两者不是同一对象,而不同对象也有可能值相等,这就无法确定了。
理想情况是,只有是同一个对象,hashcode才相同,与值是否相同无关。13、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常!
(应该是没有针对问题的确切的答案,当前的add方法放入的是哪个对象,就调用哪个对象的compareTo方法,至于这个compareTo方法怎么做,就看当前这个对象的类中是如何编写这个方法的)
实验代码:
public class Parent implements Comparable {
private int age = 0;
public Parent(int age){ this.age = age; }
public int compareTo(Objecto) {
System.out.println("method of parent");
Parento1 = (Parent)o;
return age>o1.age?1:age<o1.age?-1:0; }}
public class Child extends Parent {
public Child(){super(3); }
public int compareTo(Objecto) {
System.out.println("method of child");
// Childo1 = (Child)o;
return 1; }}
public class TreeSetTest {
public static void main(String[]args) {
TreeSetset = new TreeSet();
set.add(new Parent(3));
set.add(new Child());
set.add(new Parent(4));
System.out.println(set.size()); } }
总结:
Collection接口中规定,有些集合可以重复,有些不可以,有些有序,有些无序、
List : 可以重复, 有序
Set集合:
不允许元素重复。对于Set集合,它只能普通的迭代器来遍历这个集合。
Set集合有多个子类,这里重点学习开发时最最常用的
HashSet
LinkedHashSet
TreeSet
HashSet:底层使用的哈希表结构,它不保证元素有序。并且不允许元素重复。它还是线程不同步。
查询快,但是无法保证存取有序。
哈希表:
底层使用的还是数组,只不过在存储的时候,不是从数组的第一个空间开始存储数据,由于集合中存储的都是
对象,这个当要给这个哈希表中存储对象的时候,它会拿着这个对象,然后根据一种算法,算出这个对象在
这个数组中存储的位置。然后在把这个对象存储到计算出来的这个角标的位置上。
而根据对象计算角标的这个算法,我们称为哈希算法。由于每个对象给哈希表中存放的时候,都需要和这个算法进行
结合计算出位置,所有每个对象都应该具备这个算法。这样按照面向对象的原则。所有对象共有的功能,应该全部
抽取到父类中。因此这个算法就被定义在Object类中,这个算法就是hashcode方法。
当两个对象通过哈希算法出来的哈希值相同的时候,我们把这种现象称为哈希冲突。当2个对象的哈希值相同的时候,
这时还会调用对象的equals方法,再进行比较,如果比较的结果true,那么这时就认为两个对象是同一个,就不存储
第二个对象。如果比较的结果false,就说明两个对象不是同一个,肯定要存储这个对象。
HashSet集合到底是如何保证元素的不重复:
当给HashSet集合中存放对象的时候,会先根据对象的hashCode方法计算一个哈希值,通过这个哈希值确定对象的存储位置。
如果多个对象的哈希值相同,然后再用对象的equals方法比较到底是不是同一个。是就不存。
以后再给HashSet集合中存储对象的时候,都需要调用对象的hashCode方法和equals方法,一般都会根据对象的特有数据,
由于hashCode方法和equals方法都是定义在Object类中的,这些方法无法使用对象的特有数据进行计算和比较吧。
这时就需要这些对象复写hashCode方法和equals方法。
以后在开发的时候,我们需要建立对象自己的哈希算法和比较方式。
需求:需要一个容器存放对象,保证元素不重复。并且还要保证存取有序。
要存放对象,可以使用集合。要保证不重复,只能使用set集合。
还需要保证有序,这时HashSet就无法满足了,这时可以使用HashSet下面的小弟LinkedHashSet
LinkedHashSet:
它的底层使用的链表+哈希表的结构,它即具备哈希表的特点,同时又具备链表的特点。
哈希表是查询快,链表增删快。所有LinkedHashSet它增删也快,查询也快。
它的好处可以保证数据的存取一致。
TreeSet集合:
使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
其实是告诉我们TreeSet集合可以存入其中的元素进行自然排序。说明在使用TreeSet集合时,可以使用元素
的自然顺序排序,也可使用 Comparator 进行排序。
特点:线程不同步。底层使用的是二叉树(红黑树、左右子树)数据结构。然后可以对存入其中得元素排序。
树结构:
给TreeSet集合中存储对的时候,每存放一个对象,都需要和集合中其他的对象做比较。从而且其位置和大小。
如何去比较呢?存放的是对象,既然要比较,肯定是调用了对象的比较功能,来比较出两个对的关系。
给TreeSet集合中存放自定义对象:
当给TreeSet集合存储对象的时候,由于TreeSet集合可以给存入的对象进行排序。
那么就要求存入TreeSet集合的所有对象必须具备比较功能,如果存入的对象,不具备比较功能,
这时TreeSet集合就无法通过比较大小了,那么就导致无法排序。
要求对象必须具备比较功能,这时对象所属的类必须实现Comparable接口,并且实现其中的
compareTo方法。
当把对象存入到TreeSet集合中的时候,那么TreeSet集合的底层会把存入的对象,转成Comparable类型
然后调用其compareTo方法,从而比较出两个对象的大小,进而确定如何存放这些对象,以及他们的顺序。
TreeSet集合保证对象的唯一条件是:
是通过对象的compareTo方法的返回值来确定对象是否已经存在。如果这个方法返回值零,就认为当前这个对象在集合中已经存在。
它就不会把当前对象存放在结合中。如果不是零,就说对象不同,继续存储。
当给TreeSet集合中存放对象时,要求对象必须具备比较功能,可是当对象的已经具备了比较功能,
这个功能不符合我们的比较条件。这时怎么解决?一般情况可以让写个类去继承对象所属的类,然后
复写掉用其的比较大小的方法,建立适合我们自己的比较方式。
但是有些类不是最终类,无法继承。
当真的需要把一个对象存放在TreeSet集合中时,对象的比较功能,不满足我们要求的时候,我们在创建
TreeSet集合时,给TreeSet本身传递一个比较器。让TreeSet集合自身具备比较的功能。这样就可以完成
对象的比较不适合我们比较需求,然后在创建TreeSet时,建立TreeSet自己的的比较方式。
在给TreeSet集合存储对象时,如果对象自身具备比较功能,那么就可以使用对象自己的比较功能。
但是当对象不具备比较功能时,获取对象具备的比较功能,不适合我们使用,可以给集合自身传递比较功能。
=======================================================
Collection接口:
|
|----List :有序、重复、有角标
|---- ArrayList:底层使用的可变数组结构,不同步,增删慢,查询快
|---- LinkedList:底层使用的链表结构,不同步,增删快,查询慢
|---- Vector:底层也使用的可变数组,同步的,增删查询都慢。在JDK1.2之后,它被ArrayList代替。
|
|----Set:无序,不重复
|---- HashSet:底层使用的哈希表结构,不同步,增删慢,查询快
|----- LinkedHashSet:底层使用的链表+哈希表,不同步,增删快,查询快,可以保证存取顺序一致。
|---- TreeSet:底层使用的二叉树结构,不同步,可以排序。
查阅API应该掌握技巧:
1、首先查看整个类的继承体系,了解最顶层的功能,创建最底层的对象。
2、当我们需要使用某个具体子类的功能时,采取查看这个子类的具体功能,如果不需要,就不用关心子类的具体功能。
3、在JDK的继承体系中,一般情况下类名都具备一定的标识作用。通过类名,基本就可以知道这个类的大体功能。
举例:看到类名末位是List就知道这个容器有序,可以重复,有角标。看到Set就值无序,不重复。
ArrayList,array就代表是这个容器的数据结构。hash知道底层肯定是哈希表,Tree底层
使用的就是二叉树,这个容器就可以排序。
转载于:https://my.oschina.net/Sallens/blog/301662