java集合常用API
Java 集合类可以用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组,而内存中对数据进行存储和管理的“容器”有:数组,集合。但数组有一定的弊端: ①数组的长度不可变 ②数组存储的数据类型比较单一 ③数组的API较少,没有插入,删除等方法 ④数组存储元素是有序的,对于无序的无能为力而集合相对于数组的这些弊端做了优化: ①集合的长度可变 ...
Java 集合类可以用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组,而内存中对数据进行存储和管理的“容器”有:数组,集合。
但数组有一定的弊端:
①数组的长度不可变
②数组存储的数据类型比较单一
③数组的API较少,没有插入,删除等方法
④数组存储元素是有序的,对于无序的无能为力
而集合相对于数组的这些弊端做了优化:
①集合的长度可变
②集合可以存储任意数据类型,因为默认存储的是Object类型
③ 集合中的API比较丰富,有增,删,改,查,插,大小等操作
④集合底层存储数据的结构较多(比如,数组,链表,二叉树)
Collection集合与数组间的转换
集合 –> 数组 : toArray()
数组 –> 集合 : Arrays.asList(T...t)
注意:
List:使用Collection集合存储数据,要求数据所在的类满足:必须重写equals方法
Set:存储元素所在类的要求:要求必须重写hashCode和equals方法
TreeSet:自然排序的情况下该对象的类必须实现 Comparable 接口,且重写compareTo()方法与equals()方法
说明:Arrays.asList(…) 方法返回的 List 集合既不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合
Java 集合可分为 Collection 和 Map 两种体系
Collection常用接口:
Set:元素无序、不可重复的集合
List:元素有序,可重复的集合
Map接口:具有映射关系“key-value对”的集合
|----Collection |----List |----ArrayList(主要实现类):底层是用数组实现的,线程不安全的,比Vector 效率高。增删慢,查找快。 |----Vector:底层是用数组实现的,线程安全的,效率低 |----LinkedList:底层是用链表实现的,增删快,查找慢 |----Set : 存储的元素是无序的且不可重复的 |----HashSet(主要实现类):底层是创建了hashMap对象 |----LinkedHashSet:继承了HashSet,底层实现原理和HashSet一样。 但是LinkedHashSet可以按照元素添加的顺序进行遍历。因为LinkedHashSet 底层维护了一对指针(链表)用来记录元素添加的顺序。 |----TreeSet:可以对对象中的属性进行排序 |
Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。
注:JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List)实现。
在 Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理;从 JDK 5.0 增加了泛型以后,Java 集合可以记住容器中对象的数据类型
遍历Collection的两种方式: Iterator和foreach循环
增强for循环 :只能用于数组和集合
Iterator 接口: 用来遍历集合中的元素
增强for循环:(foreach循环)
格式:
for(元素的类型 临时变量 : 数组、集合的对象名){
}
Collection接口之List接口
List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
常用实现类主要区别:
|----ArrayList(主要实现类):底层是用数组实现的,线程不安全的,比Vector效率高。增删慢 查找快。 |----Vector:底层是用数组实现的,线程安全的,效率低 |----LinkedList:底层是用链表实现的,增删快,查找慢 |
①ArrayList底层是用数组存储数据的,线程不安全的
②构造器
a)new ArrayList(); //默认创建一个长度为10的数组
b)new ArrayList(int initialCapacity) //创建一个长度为initalCapcity的数组
如何向ArrayList中添加数据?或ArrayList的底层实现?
创建一个ArrayList空参的对象,底层会创建一个长度为10的数组。当我们向集合中放第11个元素的时候会进行扩容。扩容为原来数组长度的1.5倍。再把原来数组中的内容copy到新的数组中。如果我们知道数组元素的个数建议使用new ArrayList(int initialCapacit)。
注意List的这两个方法:
remove(int index)
remove(Object obj)
ArrayList al = new ArrayList();
al.add("aaa");
al.add("bbb");
al.add(1);
al.remove(1); //删除当前集合对应的索引值上的元素。(bbb)
al.remove(new Integer(1)); //删除当前集合中对应的元素(1)
System.out.println(al);
Collection接口之set接口
- Set接口是Collection的子接口,set接口没有提供额外的方法
- Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
- Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法
常用实现类
|----HashSet(主要实现类):底层是创建了hashMap对象 |----LinkedHashSet:继承了HashSet,底层实现原理和HashSet一样。 但是LinkedHashSet可以安照元素添加的顺序进行遍历。因为LinkedHashSet 底层维护了一对指针(链表)用来记录元素添加的顺序。 |----TreeSet:可以对对象中的属性进行排序 |
Set存储的数据特点:无序的且不可重复的
无序的:指的不是随机性,根据自定义类中的hashCode方法返回的值来决定在数组中存放的位置
不可重复的:指的是调用自定义类中的equals方法进行比较,如果返回的是true认为两个对象相同,反之则不相同。
如何向HashSet中添加数据?或HashSet的底层实现原理?
当我们向HashSet中存放数据a时,会先根据该对象中的hashCode方法返回的值决定存放在数组中的位置。如果存放的位置没有其它元素那么直接存放。如果存放的位置已经有了其它元素b时,会调用a的equals方法进行内容的比较。如果返回的是true那么认为两个元素是相同的则不能再次存放。如果返回的是false那么认为两个元素不同。以链表的形式进行存放。
注:
如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。(可以是修改后的equals相等mx)
存储元素所在类的要求:要求必须重写hashCode和equals方法
Collection接口之set接口之TreeSetTreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。
自然排序:
自然排序:TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序排列
如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。
实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。
因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同一个类的对象
对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过 compareTo(Object obj) 方法比较返回值
当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保证该方法与 compareTo(Object obj) 方法有一致的结果:如果两个对象通过 equals() 方法比较返回 true,则通过 compareTo(Object obj) 方法比较应返回 0
定制排序:
TreeSet的自然排序是根据集合元素的大小,进行元素升序排列。如果需要定制排序,比如降序排列,可通过Comparator接口的帮助。需要重写compare(T o1,T o2)方法。
利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
要实现定制排序,需要将实现Comparator接口的实例作为形参传递给TreeSet的构造器。
此时,仍然只能向TreeSet中添加类型相同的对象。否则发生ClassCastException异常。
使用定制排序判断两个元素相等的标准是:通过Comparator比较两个元素返回了0。
TreeSet可以对元素进行排序 要求:元素的类须必须一致
排序有两种方式:自然排序 vs 定制排序
1自然排序
①实现Comparable接口
②重写compareTo方法
③按照属性进行排序
④添加元素
2 定制排序
①创建一个Comparator实现类的对象
②将Comparator对象传入TreeSet的构造器中
③重写compare方法
④按照属性进行排序
⑤添加元素
自然排序的情况下该对象的类必须实现 Comparable 接口,且重写compareTo()方法与equals()方法
Map接口
|----Map |----HashMap(主要实现类) : 底层是用数组来存放数据的(数组 + 链表),线程不安全的HashMap中可以存放null值 |----LinkedHashMap:继承了HashMap底层实现和HashMap一样。 LinkedHashMap可以安照添加元素的顺序进行遍历。因为底层维护了一张链表用来记录存放的元素的顺序。 |----TreeMap:用来对Key中的元素进行排序。 |----Hashtable : 底层是用数组来存放数据的(数组 + 链表),线程安全的 Hashtable中不可以存放null值 |----Properties : 用来读取配置文件中的内容。读取的内容都是字符串。 key和value都是String类型 |
HashMap和Hashtable对比?
HashMap: 底层是用数组来存放数据的(数组 + 链表),线程不安全的HashMap中可以存放null值
Hashtable: 底层是用数组来存放数据的(数组 + 链表),线程安全的
Hashtable中不可以存放null值
HashMap的底层实现原理?
当我们向HashMap中存放一个元素(k1,v1),首先会根据k1的hashCode方法来决定在数组中存放的位置。如果当前位置没有其它元素则直接存放。如果当前位置有其它元素(k2,v2),会调用k1的equals方法和k2进行对比。如果返回值是true则代表内容相同,那么v1会覆盖v2.如果返回的是false则以链表的形式进行存放。当链表的长度为8时,链表将会改成红黑树进行存放。
Map之TreeMapTreeMap 的 Key 的排序:
自然排序:
TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
定制排序:
创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口
结构说明:
①new HashMap() : 创建一个空参的构造器。那么底层默认创建一个长度为16加载因子为0.75。当我们向集合中添加元素超过12时会进行扩容,扩容为原来大小的2倍。
③HashSet的底层是:HashMap(将数据存放在Key中)
④LinkedHashSet的底层是:LinkedHashMap(将数据存放在Key中)
⑤TreeSet的底层是 : TreeMap(将数据存放在Key中)
Iterator迭代器接口
terator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建 Iterator 对象,则必须有一个被迭代的集合。
常用方法:
hasNext() : 是否还有下一个元素
next(): ①指针下移 ②获取元素
注:
Iterator常见的两种错误:
Collection coll = new ArrayList();
coll.add("aaa");
coll.add(123); // 装箱
coll.add(456);
//错误 方式一 :coll.iterator();因为每次循环底层都创建了一个新的对象,如下图
while(coll.iterator().hasNext()){
System.out.println(coll.iterator().next());
}
Iterator iterator = coll.iterator();
//错误方式二 : 因为每next一次指针就会下移,一旦没有元素就会报错
while(iterator.next() != null){
System.out.println(iterator.next());
}
Collections工具类
注意Collection集合和Collections工具类的区别:
Collections是工具类:
Collections 是一个操作 Set、List 和 Map 等集合的工具类,Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
排序操作:(均为static方法)
l reverse(List):反转 List 中元素的顺序
l shuffle(List):对 List 集合元素进行随机排序
l sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
l sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
l swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
查找、替换
l Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
l Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
l Object min(Collection)
l Object min(Collection,Comparator)
l int frequency(Collection,Object):返回指定集合中指定元素的出现次数
l void copy(List dest,List src):将src中的内容复制到dest中
l boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
注:
(
操作数组的工具类:Arrays
操作集合的工具类:Collections
)
再次总结底层实现:
List之 ArrayList的底层实现?
* 创建一个ArrayList空参的对象,底层会创建一个长度为10的数组。当我们向集合中放第11个元素的时候会进行扩容。
* 扩容为原来数组长度的1.5倍。再把原来数组中的内容copy到新的数组中。
* 如果我们知道数组元素的个数建议使用new ArrayList(int initialCapacit)。
Set之HashSet的底层实现原理?
* 当我们向HashSet中存放数据a时,会先根据该对象中的hashCode方法返回的值决定存放在数组中的位置。
* 如果存放的位置没有其它元素那么直接存放。如果存放的位置已经有了其它元素b时,会调用a的equals方法进行内容的比较。
* 如果返回的是true那么认为两个元素是相同的则不能再次存放。如果返回的是false那么认为两个元素不同。以链表的形式进行
* 存放。
Map之HashMap的底层实现原理?
当我们向HashMap中存放一个元素(k1,v1),首先会根据k1的hashCode方法来决定在数组中存放的位置。如果当前位置没有其它元素则直接存放。如果当前位置有其它元素(k2,v2),会调用k1的equals方法和k2进行对比。如果返回值是true则代表内容相同,那么v1会覆盖v2.如果返回的是false则以链表的形式进行存放。当链表的长度为8时,链表将会改成红黑树进行存放。
更多推荐
所有评论(0)