集合与数组一样,也是一个容器,与数组不同的是,数组长度固定,集合的长度不定,可以无限的向集合中添加元素,而且集合中存储的元素类型可以随意,可以是不同的类型,只能是引用类型。
集合中有三大组件:List,Set,Map(List和Set 是Collection的子接口,Map不是)
Colletion集合的框架结构:(在util包下)
Map集合的框架结构:
1.Collection接口中常用的方法:
增加:1:add(元素) 将指定对象存储到容器中
2:addAll(集合) 将指定集合中的元素添加到调用该方法和集合中
删除:3:remove(元素) 将指定的对象从集合中删除
4:removeAll(集合) 将指定集合中的元素删除
修改:5:clear() 清空集合中的所有元素
判断:6:isEmpty() 判断集合是否为空
7:contains(元素) 判断集合何中是否包含指定对象
8:containsAll(集合) 判断集合中是否包含指定集合
9:元素.equals(元素)判断两个对象是否相等
获取: 10:int size() 返回集合容器的大小
转成数组:11: toArray() 集合转换数组
2.迭代器(Iterator接口)原理:
迭代器相当于一个游标,最初获取迭代器时,迭代器的位置在所有元素的前面,每迭代一个元素,迭代器向后移动一个位置。方法:hasNext()//游标不移动,仅仅判断是否存在下一个元素 next();//取值,游标向后移动
3.List接口:
继承Collection接口,相对有序存储,可以存储相同元素(不排重,可重复),可以通过下标访问集合元素,List接口中可以使用独有的迭代器ListIterator(是Iterator的子接口,hasPrevious(),previous()),具有反向遍历的功能
方法:(有序,所以有下标,但是有不去重)
1:增加
void add(int index, E element) 指定位置添加元素
boolean addAll(int index, Collection c) 指定位置添加集合
2:删除
remove(int index) 删除指定位置元素
3:修改
set(int index, E element) 返回的是需要替换的集合中的元素
4:查找:
get(int index) 注意: IndexOutOfBoundsException
int indexOf(Object o) // 找不到返回-1
lastIndexOf(Object o)
5:求子集合
subList(int fromIndex, int toIndex) // 不包含toIndex
4.泛型
List list = new ArrayList();//== List<Object> list = new ArrayList<Object>();不规范
List<Student> list = new ArrayList<Student>();//确定输入的类型,规范!
a.泛型就是可以表示一个广泛数据类型的类型参数(泛型只能表示引用类型),把数据类型作为参数来传递。
b.泛型的声明:方法、类、接口
1)泛型可以声明在方法中:(泛型方法)
public static <标识符> void fun(){}
2)泛型可以声明在类中:(泛型类)
public class 类名<标识符>{
//类体
//该类型可以在整个类中使用,静态方法不能使用类上面声明的泛型
//泛型可以在类中充当成员变量
//泛型可以在类中充当方法的返回值
//泛型可以在类中充当方法的参数
}
3)泛型可以声明在接口中:(泛型接口)
public interface 接口名<标识符>{
//成员
//泛型可以充当接口中方法的返回值
//泛型可以充当接口中方法的参数
}
c. 注:
1)标识符(占位符):只要是一个合法的标识符即可,一般情况下,只使用一个大写字母表示泛型
例:public class Person<T>{} E(Element) K(key) V(value)
2)泛型的类型与声明的类或接口不需要有任何的关系
3)泛型可以在类中充当任何的成员
4)泛型具体类型取决于实例化对象时传入的实际类型
5)泛型不能在类中声明静态属性、常量
final修饰的属性必须在声明的同时初始化,所以泛型不能声明常量
static修饰的属性是静态属性,先于对象,泛型类型取决于创建对象时传入的实际类型,所以泛型不能声明静态属性
综上所述:不能使用泛型声明静态属性、常量
6)泛型不能在类中初始化数组,但是可以声明数组 例:E[] e;
初始化数组时需要给元素进行分配空间,但是泛型类型不确定无法分配空间
7)在类中不能使用泛型声明参数个数相同的重载方法
当一个类中有两个泛型时,创建对象时,两个泛型使用相同类型替换,那么重载方法就是相同的方法(同名,参数列表也相同)
8)使用不同实际类型创建出的泛型类对象的引用不可以相互赋值
d. 受限类型
1)<?>:表示任意类型
2)<? extends T>:表示T类或者T类的子类
3)<? super T>:表示T类或者T类的父类
5.List的实现类:ArrayList、LinkedList、Vector
ArrayList类是最重要的。
与LinkedList的区别:ArrayList底层是Object数组Object[],初始容量是10,每次增加元素时,先判断数组是否能容纳,如果不能,容量扩大1.5倍(类的代码是:newCapacity = oldCapacity + (oldCapacity >> 1))。特点是:查询快、增删慢。而LinkedList的底层是链表实现的,特点是查询慢、增删快。
与Vector的区别:ArrayList是线程不安全的,效率高。Vector是线程安全的,效率低,Stack类是Vector的子类。
6. Set的实现类:HashSet、TreeSet
set接口是Collection接口的子接口,特点:无序,不可重复(可自动去重)。
如何去重?对象的相等性
引用到堆上同一个对象的两个引用是相等的,对两个引用调用hashCode方法,会得到相同的结果。如果对象所属的类没有覆盖Object的hashCode方法的话,hashCode会返回每个对象特有的序号(java是依据对象的内存地址计算出的此序号),所以两个不同的对象的hashCode值是不可能相等的。
如果想要让两个不同的Person对象视为相等的,就必须覆盖Object继下来的hashCode方法和equals方法,因为Object hashCode方法返回的是该对象的内存地址,所以必须重写hashCode方法,才能保证两个不同的对象具有相同的hashCode,同时也需要两个不同对象比较equals方法会返回true
该集合中没有特有的方法,直接继承自Collection。
HashSet类:线程不安全,存取速度快。底层是以hash表实现的。
HashSet的存储原理:
哈希表存放的是哈希值。HashSet存储元素的顺序并不是按照存入时的顺序(和List显然不同) 是按照哈希值来存的所以取数据也是按照哈希值取得。
HashSet不存入重复元素的规则.使用hashcode和equals。
元素的哈希值是通过元素的hashcode方法来获取的, HashSet首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals方法 如果 equls结果为true ,HashSet就视为同一个元素。如果equals 为false就不是同一个元素。
哈希值相同equals为false的元素是怎么存储呢,就是在同样的哈希值下顺延(可以认为哈希值相同的元素放在一个哈希桶中)。也就是哈希一样的存一列。
注:HashSet 和ArrayList集合都有判断元素是否相同的方法,HashSet使用hashCode和equals方法,ArrayList使用了equals方法
TreeSet:红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。
给TreeSet指定排序规则。
方式一:元素自身具备比较性
元素自身具备比较性,需要元素实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。
@Override
public int compareTo(Object obj) {
Person p = (Person) obj;
System.out.println(this+" compareTo:"+p);
if (this.age > p.age) {
return 1;
}
if (this.age < p.age) {
return -1;
}
return this.name.compareTo(p.name);
}
方式二:容器具备比较性
当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeSet集合的构造方法。
例如:
main: TreeSet ts = new TreeSet(new MyComparator());
class MyComparator implements Comparator {}
注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;
注意:在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较次要条件。(假设姓名和年龄一直的人为相同的人,如果想要对人按照年龄的大小来排序,如果年龄相同的人,需要如何处理?不能直接return 0,因为可能姓名不同(年龄相同姓名不同的人是不同的人)。此时就需要进行次要条件判断(需要判断姓名),只有姓名和年龄同时相等的才可以返回0.)
通过return 0来判断唯一性。
7,Map接口
注:
1.一个键(key)和它对应的值构成map集合中的一个元素。
2.Map中不能有重复的键(Key),自动去重,规则是hashCode()、equals();
3.通过key获取Value值
4.Key可以为null
5.Interface Map<K,V> K,V必须是引用数据类型
6.Map集合没有直接取出元素的方法,而是先转成Set集合,在通过迭代获取元素。
1>map.keySet(),获取key的Set集合,遍历集合,通过key获取value(map.get(key)).
2>通过获取一个entrySet集合,map.entrySet();(Entry是一个类,里面包括key和value两个属性),获取里面的键值对的值(entry.getKey(),entry.getValue())
7.Map中的key是无序的
常见方法:
1、添加:
put(K key, V value)(可以相同的key值,但是添加的value值会覆盖前面的, 返回值是前一个,如果没有就返回null)
putAll(Map<K,V> m) 从指定映射中将所有映射关系复制到此映射中(可选操作)。
2、删除
remove(key) 删除Key元素,并返回Value
remove(key,value) 判断value对不对,返回boolean
clear() 清空集合对象
replace(key,value)通过key找到元素,把对应的值改成value
replace(key,oldvalue,newvalue)
3、获取
get(key) 返回value。当指定的键不存在的时候,返回的是null。
keySet() 返回以key为元素的Set集合
entrySet();返回Entry为元素的Set集合
3、判断:
boolean isEmpty() 长度为0返回true否则false
boolean containsKey(Object key) 判断集合中是否包含指定的key
boolean containsValue(Object value) 判断集合中是否包含指定的value
4、长度:
Int size()
Map接口的实现类:HashMap\HashTable\TreeMap 继承接口SortedMap
HashMap集合:底层是哈希表数据结构,所以自动去重,但是是无序的。线程不安全,可以存入null Key,null Value。要保证键的唯一性,需要覆盖hashCode方法,和equals方法。
HashTable集合:底层是哈希表数据结构,自动去重,但无序。线程安全,不可以存入null Key,null Value。效率较低,被HashMap 替代。
TreeMap集合:底层是二叉树数据结构,可以对map集合中的键进行排序。需要使用Comparable或者Comparator 进行比较排序。
Properties类:HashTable的子类
注:配置文件(在workspace中新建的一个File文件),是以键值对的形式存储的
load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。
(流里的文件可以是任意文件!不一定非是File文件)
返回值:枚举Enumeration(功能相当于Iterator,有hasMoreElements()方法和nextElement()) elements() 返回此哈希表中的值的枚举。keys() 返回此哈希表中的键的枚举。(这两个方法都是父类HashTable的方法)
方法详见API。
Collections 和 Arrays 工具类
Collections:常见方法:
1,对list进行二分查找:
前提该集合一定要有序。
int binarySearch(list,元素);
//必须根据元素自然顺序对列表进行升级排序
//要求list 集合中的元素都是Comparable 的子类。
int binarySearch(list,元素,Comparator);//比较器
2,对list集合进行排序。
sort(list);
//对list进行排序,其实使用的事list容器中的对象的compareTo方法
sort(list,comaprator);
//按照指定比较器进行排序
3,对集合取最大值或者最小值。
max(Collection)
max(Collection,comparator)
min(Collection)
min(Collection,comparator)
4,对list集合进行反转。
reverse(list);
5,对比较方式进行强行逆转。
Comparator reverseOrder();
Comparator reverseOrder(Comparator);
6,对list集合中的元素进行位置的置换。
swap(list,index1,index2);
7,对list集合进行元素的全替换。如果被替换的元素不存在,那么原集合不变。
replaceAll(list,old元素,new元素);
8,可以将线程不安全的集合变成线程安全的集合。synchronized***
Set synchronizedSet(Set<T> s)
Map synchronizedMap(Map<K,V> m)
List synchronizedList(List<T> list)
9. 如果想要将集合变数组:
可以使用 Collection 中的toArray 方法。注意:是Collection不是Collections工具类。
传入指定的类型数组即可,该数组的长度最好为集合的size。