Java集合
Collection接口
1,List接口
特点:有序(存储和取出的顺序),可重复,有索引
1)ArrayList
ArrayList,底层是动态数组,擅长随机访问,线程不安全,适合查询,增删慢
2)LinkedList
LinkedList,底层是一个双向链表,线程不安全,适合增删,查询慢
2,Set接口
特点:无序且不可重复,元素必须不同,没有索引,不可使用简单for循环遍历
Set集合通过HashCode方法和equals方法来保证集合元素的唯一性
1)HashSet
HashSet,底层是一个HashMap实例,允许集合内只能有一个null值,虽然是存取顺序无序的,
但其内部根据HashCode(哈希值 ,不是对象地址值,是jvm算出来的int值)存储排序元素,
非线程同步HashCode()是Object中的方法,默认情况下,不同类对象哈希值不同,
但子类通过重写HashCode()可以使同类中不同实例的哈希值相同从而保证HashSet集合的唯一性
2)TreeSet
TreeSet,非线程安全,间接实现Set接口,不包含重复元素
支持两种排序方式,自然排序(comparable接口)和比较器排序(comparator比较器排序接口)
1.treeSet():根据其元素的自然排序进行排序,
自然排序指,从小到大,从a-z的方式排序,自定义类实现了comparable接口并重写compareTo方法就可以使用自然排序
compareTo返回值如果是0,则本元素和上一个元素相同,不插入
如果返回值是正数,则输出顺序和插入顺序一致,如果返回值是负数,则输出顺序和插入顺序相反.
compareTo方法中,举例:int i =this.ags-o.age是按年龄升序排序,
int i = o.age-this.age是按年龄降序排序
2.TreeSet(Comparator corparator):根据指定的比较器进行排序
在TreeSet带参构造器中创建一个匿名内部类对象,是comparator比较器的对象,然后重写compare方法,
不需要自定义类实现comparable接口。
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int i = o1.getAge() - o2.getAge();
int i2 = i == 0 ? o1.getName().compareTo(o2.getName()) : i;
return i2;
}
});
3,LinkedHashSet
继承TreeSet,由哈希表和链表实现的Set接口,由链表保证存取顺序有序,哈希表保证元素唯一性,线程不安全。
Map接口
基本方法,put,remove,clear,containsKey,containsValue,isEmpty,size
获取功能,get,KsySet,values(获取所有值的集合),entrySet(获取所有键值对对象的集合)
map集合通过get方法查不到数据会返回null
map集合遍历方式
1)遍历Map中Key的集合,根据Key找对应的值,map.keySet,map.get(key)
2)获取所有键值对对象的集合,遍历集合得到每个键值对对象,通过getKey,getValue得到键值
1.HashMap
以哈希表数据结构实现,线程不安全,HashMap添加元素,第二次添加同名键时,会覆盖之前的同名键中的值。
2.TreeMap
和TreeSet一样可以排序,使用无参构造函数时,对键进行排序
集合的遍历方式
集合的三种遍历方式
迭代器,所有集合都可以使用
简单for循环,带有索引的集合才可以使用,比如List集合,
增强for循环,最方便的遍历方式,
foreach循环内部是一个iterator迭代器,在foreach中集合添加元素会抛出并发修改异常
集合的工具类
集合的工具类,Collections类,sort,reverse(反转列表),shuffle(随机排列集合)
其中sort方法的使用需要自定义类实现自然排序或者给定比较器排序
数组的工具类,Arrays类
集合中元素都是引用类型
哈希表
jdk1.8之前,哈希表底层采用数组+链表实现,可以说是一个元素为链表的数组
jdk1.8之后,在长度较长的时候,底层实现了优化
存储过程:取元素的哈希值,与16取余,如果哈希值相同,
则对比该位置元素的内容,通过调用equals方法,如果相同则认为是同个元素,不存储
凡是使用到哈希表的集合,自定义子类需要重写equals和hashcode方法
泛型
本质是参数化类型,就是将类型由原来具体的类型参数化,然后在使用/调用时传入具体的类型
可以使用在类,方法,接口上,就是泛型类,泛型方法,泛型接口
好处,把运行时期的问题提到了编译时期,类型转换异常
避免了强制类型转换
泛型定义方式
泛型类,public class FanXing<T> {}
泛型方法,public <T> void show(T s){}
泛型接口,public class FanXing<T> implements generic<T> {},public interface generic<T> {}
接口使用了泛型,其实现类也必须实现泛型
类型通配符<?>
List<?>表示元素类型未知的List,它的元素可以匹配任何类型
这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
如果说我们不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用泛型通配符的上下限
上限,List<? extends Number>,它表示的类型是Number或者其子类型
下限,List<? super Number>,它表示的类型是Number或者其父类型
可变参数
可变参数又称参数个数可变,用作方法的形参出现,那么方法的参数个数就是可变的了
public static void sum(int... a){},此形参a其实是数组
注意,一个方法有多个参数,可变参数应该放在最后面
可变参数的使用
Arrays中的asList静态方法
List和Set接口的of方法都使用了可变参数