1.集合相对于数组的优缺点:集合长度可变,数组初始化必须声明长度;数组可存储基本类型变量和应用类型变量,集合只能存储
引用类型变量;一个集合可以存储不同类型的元素,而一个数组只能存储相同类型的元素。
2.集合的继承体系:Collection
|--List:元素有序,可以重复,有索引,如果想要用List容器存储自定义的类一定要定义自己的equals方法
|--ArrayList:底层数据结构使用的是数组,查询很方便,但是增删很慢,它的实现是线程不同步的(效
率高不判断锁)
长度可变数组的实现:ArrayList默认初始容量是10,如果数据溢出,自动增加当前数据容
量的一半所以它的容量变化为:10,15,22,33,49.........,Vector每次都是增加10容量
|--LinkedList:底层数据结构使用的是链表,增删很快,查询稍慢,它是线程不同步的
|--Vector:底层数据结构是数组,它的实现是线程同步的(效率低要判断锁),被ArrayList替代了
Vector特有一个可以取出枚举的方法
|--Set:元素无序(输入顺序和输出顺序不一样),不可重复,
|--HashSet:底层数据结构是哈希表,线程是非同步的,如果想要用HashSet容器存储自定义的类一定要定义自己的equals和hashCode方法
哈希表数据结构存储过程为:先判断元素的哈希值是否相同(调用hashCode()方法),不同的话就进行存储,不再执行别的操作,如果相同的话再判断是否为同一对象(调用equals()方法)。
|--TreeSet:可以对Set中的元素进行排序(但它任然是无序的),它的底层数据结构是二叉树。此实现线程是不同步的.
第一种排序方法:要存储的元素对象所属的类必须实现Comparable接口,并覆写compareTo方法,在其中自定义比较规则。(只存储唯一元素的话让compareTo方法返回0是唯一标准)
存入的元素会调用compareTo依次倒序与之前的每个元素进行比较。
第二种排序方法:在集合初始化时就自定义集合的比较规则,新建一个类,让该类实现Comparator接口并复写compare()和equals()方法,将该类作为参数传给集合构造器,那么这个集合
就具 备了比较性。当元素和集合都具备比较性时,优先以集合的比较规则为准。
| Map:和Set很像,其实Set底层调用了Map,将元素按照映射的关系一对一对进行存储,键必须是唯一的(键可以为null但值不可以为null)
|--HashTable:底层是哈希表数据结构,null不可以作为键或者值,它的线程时同步的,用作键的对象必须实现hashCode和equals方法
|--HashMap:底层是哈希表数据结构,null可以作为键和值,该线程时不同步的。
|--TreeMap:底层是二叉树结构,线程不同步,可以用于给map集合中的键进行排序
ArrayList:
注意:1.在List中存放自定义类型时,List方法中的参数是Object,会对参数进行默认提升导致对象的函数无法 识别,这时就必须对对象先进行强转
比如:
class Person
{
private String name;
Person(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
}
class test
{
public static void main(String []args)
{
ArrayList al = new ArrayList();
al.add(new person("Bob"));
al.add(new Person("Alice"));
Iterator i = al.iterator();
while(i.hasNext())
{
System.out.println(i.next().getName());//此处会报错:找不到符号getName()因为add方法将Person对象提升为了Object,而Object中没有getName方法,为了解决该问题只要将i.next()在强转成Person类型
}
}
}
2.ArrayList中的contains(Object obj)和remove(Object obj)方法实际上调用的自身的indexOf(Object obj)方法,而indexOf方法又调用的是obj的equals方法,所以要想使用contains()和remove()方法,必须先定义好obj的equals方法。
迭代器:Iterator
常见用法:
方法一:
Iterator i = 集合名称.iterator();
while(i.hasNext())
{
E = i.next();//等等对i.next的操作
}
方法二:该方法执行完后所有内存都会释放,比方法一更好
for(Iterator i = 集合名称.iterator();i.hasNext()))
{
//对i.next()进行一系列操作
}
注意:a):next()方法是在完成查找操作的同时将迭代器位置前移,可以认为java迭代器是位于集合两个元素的中间,当调用next()时,迭代器就越过下一个元素并将刚刚越过的元素的引用返回。所以必须调用next()方法,迭代器才能实现将集合中元素遍历的目的.
b):在迭代期间不能修改列表结构(增添,删除,改变索引等但是可以 改变元素值),只有Iretaror的remove()方法可以修改列表结构
ListIterator:系列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。ListIterator 没有当前元素;它的光标位置 始终位于调用previous() 所返回的元素和调
用 next() 所返回的元素之间。在长度为 n 的列表中,有n+1 个有效的索引值,从 0 到 n(包含)。如果要在迭代期间修改列表结构的话就应该使用ListIterator,ListIterator一个重要的特点就是能够
获取列表的各个位置.
HashMap:1.该集合的添加和修改都是put()方法,对同一个键用put赋值两次,该键对应的值是后调用方法中传入的值,该方法会返回被覆盖的值。
class MapDemo
{
public static void main(String [] args)
{
HashMap<Integer,String> hm = new HashMap<Integer,String>();
System.out.println(hm.put(1,"haha"));
System.out.println(hm.put(1,"hehe"));
hm.put(3,"xixi");
System.out.println(hm);
//输出结果为:null
haha
{1=hehe, 3=xixi}
}
}
3.两个工具类:|--Collections:该类没有构造器,方法全是静态方法
几个常见的方法:sort : public static <T extends Comparable<? super T>> void sort(List<T> list,根据元素的自然顺序 对指定列表按升序进行排序。列表中的所有元素都必须实现
Comparable 接口,注意只能用于List及其子类。
sort : public static <T> void sort(List<T> list, Comparator<? super T> c) , 根据指定比较器产生的顺序对指定列表进行排序。
max : public static <T> T max(Collection<? extends T> coll,Comparator<? super T> comp)根据指定比较器产生的顺序,返回给定 collection 的最大元素
binarySearch: public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)获得指定元素在列表中的索引,前提是列表必须有序。
binarySearch: public static <T> int binarySearch(List<? extends T> list, T key,Comparator<? super T> c),对不具备比较性的元素根据比较器的规则获得指定元素的位置,调用该方法
时 一定要先用sort ( list ,Comparator<? super T> c)对列表进行排序
replaceAll :public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal),使用另一个值替换列表中出现的所有某一指定值
reverseOrder : public static <T> Comparator<T> reverseOrder()返回一个比较器,它强行反转实现 Comparable 接口那些对象 collection 上的自然顺序。
reverseOrder : public static <T> Comparator<T> reverseOrder(Comparator<T> cmp)返回一个比较器,它强行反转指定比较器的顺序。
synchronizedList : public static <T> List<T> synchronizedList(List<T> list)返回由指定列表支持的同步(线程安全的)列表。为了保证按顺序访问,必须通过返回的列表完成对底层列表的
所有访问. 在返回的列表上进行迭代时,强制用户手工在返回的列表上进行同步. 该方对Set , Map也同样适用。
shuffle : public static void shuffle(List<?> list)使用默认随机源随机更改指定列表的序列。所有序列更改发生的可能性都是大致相等的。
|Arrays:全是静态方法用来处理一些问题,详见API文档
4.数组和集合的互相转换
(数组转集合)ArrayList.asList() :public static <T> List<T> asList(T... a)返回一个受指定数组支持的固定大小的列表(不可以再进行增删),可以使数组和集合相互转换,用集合的思想和方法来解决问题
如果数组中元素全是引用类型,那么变成集合时,数组的元素就是集合的元素;
如果数组中元素全是基本类型,那么变成集合时,会将数组作为集合中的元素进行存储。
int[] i ={1,2,3,4};
12.集合
System.out.println(i); //打印结果为 :[I@160a26f]
List<int []> li = Arrays.asList(i); [I@160a26f]是同一地址值
System.out.println(li);
....................................
Integer[] j = {1,2,3,4};
System.out.println(j);
List<Integer> lj = Arrays.asList(j); //打印结果为:[Ljava.lang.Integer;@f39b3a
System.out.println(lj); [1, 2, 3, 4]
(集合转数组)Collection接口中 toArray<T> : T[] toArray(T[] a)返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。如果指定的数组能容纳该 collection,则返回包 含 此 collection 元素的数组。否则,将根据指定数组的运行时类型和此 collection 的大小分配一个新数组。 如果指定的数组能容纳 collection 并有剩余空间(即数组的元素比 collection 的元素多) 那么会将数组中紧跟在 collection 末尾的元素设置为 null参数a
- 存储此 collection 元素的数组(如果其足够大);否则, 将为此分配一个具有相同运行时类型的新数组。