黑马程序员——学习笔记08.Java集合
2014-01-04 12:39
176 查看
----------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流!
----------------------
----------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流!
----------------------
详细请查看:http://edu.csdn.net
----------------------
集合的基本概念
1.java是面向对象的设计开发编程语言,所操作的元素都是以对象为单位的。集合就是存在对象的容器,集合是存储对象最常用的一种方式。集合中可以存储任意类型的对象,而且长度可变。在程序中有可能无法预先知道需要多少个对象,那么用数组来装对象的话,长度不好定义,而集合解决了这样的问题。
2.与数组的异同:数组和集合类都是容器;数组长度是固定的,集合长度是可变的;数组和结合都可以存储基本数据类型和对象,数组在定义的时候就需要指定存储的数据类型,而集合可以不用。
3.集合的作用:是用来存储对象数据的,也是用来操作数据的,例如:增、删、查、改等功能
集合常用的基本体系
---|Collection: 单列集合
---|List: 有存储顺序,可重复
---|ArrayList: 底层由数组实现,查找快,增删慢
---|LinkedList: 底层由链表实现,增删快,查找慢
---|Vector:和ArrayList原理相同,但线程安全,效率略低。
---------------------------------------------------------------------
---|Set: 无存储顺序, 不可重复
---|HashSet:底层是按照哈希表数据来存储对象元素,底层实现
实际上是一个HashMap实例,
---|LinkedHashSet;是由哈希表和链表双重实现的。存储是
按照先后顺序排列的,在HashSet基础上有所改进。
---|TreeSet:底层是按照二叉树原理来存储数据的。存储元素
要实现Comparable接口或者自定义一个比较器。
--------------------------------------------------------------------
---| Map: 双列集合(键值对)
---|HashMap:实现原理与HashSet相同
---|LinkedHashMap:实现原理与LinkedHashSet相同。
---|TreeMap:实现原理与TreeSet相同
---|Hashtable: 线程安全的。
---|Properties:永久性的属性集,键值对是按字符串形式存在的
List集合:有存储顺序, 可重复,可存储null元素
1.ArrayList
实现原理:数组实现。因为数组的内存空间地址是连续的.ArrayList底层维护了一个Object[]用于存储对象,默认数组的长度是10。可以通过 new ArrayList(int size)显式的指定用于存储对象的数组的长度。当默认的或者指定的容量不够存储对象的时候,容量自动增长为原来的容量的1.5倍。
优点:查找快。数组是可以直接按索引查找, 所以查找时较快
缺点:增删慢。由于ArrayList是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素. 所以慢。
假设向数组的0角标位置添加元素,那么原来的角标位置的元素需要整体往后移,并且数组可能还要增容,一旦增容,就需要要将老数组的内容拷贝到新数组中.所以数组的增删的效率是很低的.
2.LinkedList
实现原理:链表实现,增删快,查找慢。由于链表结构的数据在内存中的地址不连续,所以每个元素中保存的有下一个元素的索引值。
优点:增删快。增加时只需要让前一个元素记住新元素的索引,让新元素记住下一个元素就可以了。删除时让这个元素的后一个元素记住这个元素的前一个元素即可. 这样的增删效率较高。
缺点:查找慢。查询元素时需要一个一个的遍历, 所以效率较低。虽然元素有对应的索引,但是查找的时候,需要从头往下找,显然是没有数组查找快的
3.Vector
实现原理和ArrayList相同,区别就是它是线程安全的,当多个线程对集合中的数据进行操作时建议使用此集合,但效率会降低。单线程使用ArrayList较为常见。
在实际开发中使用ArrayList频率较高。
Set集合:无存储顺序, 不可重复
1.HashSet
实现原理:哈希表实现。实际是通过HashMap来实现功能的。创建HashSet对象时,底层是创建了一个HashMap对象来完成其功能的。
实现特点: HashSet存储元素的顺序并不是按照存入时的顺序(和List显然不同)而 是按照哈希值来存储的,所以调用和删除数据也是按照哈希值取得。
HashSet不存入重复元素的规则:调用存入元素的hashcode()方法和equals()方法。那是如何具体实现的呢?当你试图把对象加入HashSet时,HashSet会使用对象的hashCode()计算出存入对象的哈希值来判断对象存入的哈希位置,同时也会与其他已经加入的对象的hashCode进行比较,如果没有相等的哈希值,HashSet就会认为对象没有重复出现。所以如果对象的hashCode值是不同的,那么HashSet会认为对象是不可能相等的。如果存入元素(对象)的hashCode值相同,是不是就无法存入HashSet中了吗?当然不是,会继续使用equals进行比较.如果调用equals返回true 那么HashSet认为新加入的对象重复了所以加入失败.如果equals()方法返回false那么HashSet 认为新加入的对象没有重复,新元素可以存入集合中。
因此我们自定义类的时候通常需要重写hashCode()和equals()方法,以确保当用HashSet集合来存入元素时,没有存入相同元素,造成资源浪费。当要删除一个集合中元素时,会根据指定元素的hashCode值来查找对应元素,如果找到有对应的元素的hashCode相同,那么就放回true,删除成功。如果没有,则返回false。
总结:
元素的哈希值是通过元素的hashcode方法来获取的, HashSet首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals方法 如果 equls方法返回结果为true,HashSet就视为同一个元素,存入失败。如果equals方法返回结果为false,就不是同一个元素,可以存入这个元素。所有自定义一个类时,覆写了hashCode方法就一定要覆写equals方法。
注意:
如果一个对象成功添加到了HashSet中,那么最好不要修改这个对象中参与到hashcode方法中的属性值。因为一旦修改了,这个对象的hashCode值发生改变了,在修改后的这个对象的hashCode对应的哈希表位置中并没有这个对象,再去删除这个元素的时候就无法删除成功,易造成内存泄露。HashSet集合中元素是无序的。它不保证集合的迭代顺序,特别是它不保证该顺序恒久不变.
此类允许使用 null 元素。
2.TreeSet
实现原理:二叉树的数据结构,默认对元素进行自然排序,如果使用comparaTo或者compara方法在比较两个对象,返回值为0,那么元素重复,元素添加失败。
实现特点:TreeSet可以自然排序,那么TreeSet也可以按指定规则对元素进行排序。TreeSet是怎样进行存储元素的呢?怎样进行排序的呢?TreeSet在存储元素时,存储元素(对象)必须具备比较性(实现Comparable接口覆写comparaTo(Object obj)方法)或者按照指定按照指定比较规则(自定义比较器)进行对象的比较来进行排序。当元素自身具备比较性,需要元素实现Comparable接口,重写compareTo方法,这种方式叫做元素的自然排序也叫做默认排序。当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备比较规则.需要定义一个类实现接口Comparator,重写compare(Object o1,Object o2)方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。
注意:
当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;在重写compareTo或者compare方法时,必须要明确比较的主要条件相等的情况下要比较次要条件。假设姓名和年龄一致的人为相同的人,如果想要对人按照年龄的大小来排序,如果年龄相同的人,需要如何处理?不能直接比较放回0,因为两个人姓名不同年龄相同是两个不同的人。此时就需要进行次要条件判断,当年龄相同需要判断姓名,只有姓名和年龄同时相等时才可以返回0。这样可以避免遗漏要存入的不同数据。
此类不允许使用null元素。
3.LinkedHashSet
实现原理:使用链表和哈希表双重结合进行存储元素。元素的顺序是按照存储添加的顺序进行排列的。但需要对一组数据进行存储,并且去除重复元素,按照存入时的顺序,可以
用LinkedHashSet。此类允许使用null元素。
Map集合:双列集合,是以键值对形式存在的。键要求不能重复,值可以重复。
1.HashMap
实现原理:通过哈希表来实现Map接口的。
实现特点:线程不同步的,不安全。允许存入null键和null值。存入元素必须要覆写hashCode()和equals()方法。
2.LinkedHashMap
实现原理:通过哈希表和链接列表双重实现Map接口的。
实现特点:具有可预知的迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。是继承HashMap的。
3.TreeMap
实现原理:通过二叉树原理来实现Map接口的。
实现特点:可对Map集合中的键进行排序,但存入的元素必须要实现Comparable接口或自定义比较器实现Comparator接口。不允许存入null键和null值。
4.Hashtable
实现原理:通过哈希表来实现Map接口的。
实现特点:线程是同步的,安全的。不允许存入null键和null值。效率较低。
5.Properties
实现原理:是继承Hashtable,它表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
实现特点:因为 Properties 继承于 Hashtable,所以可对 Properties 对象应用 put 和 putAll 方法。但不建议使用这两个方法,因为它们允许调用者插入其键或值不是 String 的项。相反,应该使用 setProperty 方法。如果在“不安全”的 Properties 对象(即包含非 String 的键或值)上调用store或save方法,则该调用将失败。类似地,如果在“不安全”的Properties 对象(即包含非 String 的键)上调用 propertyNames或list方法,则该调用将失败。
Iterable接口:Collection的父接口,实现了Iterable的类就是可迭代的,并且支持增强for循环。该接口只有一个方法即获取迭代器的方法iterator(),可以获取每个容器自身的迭代器Iterator。Collection接口进程了Iterable接口,该接口只有一抽象方法iterator(),返回迭代器Iterator。所有Collection体系中的集合都具备获取自身迭代器的方法,因为数据结构不同,每个子类集合都进行了重写。在进行迭代器遍历元素时,不能通过集合对元素进行操作。如果操作,那么迭代失败。
Iterator迭代器接口:List有一个特有迭代器ListIterator,增添逆序进行迭代和增加设置元素的方法。
Collections:集合工具类,包含了对集合进行排序,查找等功能。
综合练习:字符串”abadcd-0o*7ffbaeba”中包含几种英文字符,每种英文字符出现了多少次,按次数排序并输出。例如:c : 1,e : 1,d : 2,f : 2,b : 3,a : 4
//定义一个方法具备将指定的字符串中字符输出英文字符次数排序。 public static void listString1(String str) { char [] arr =str.toCharArray(); //使用TreeMap集合,key的顺序是按照元素的自然顺序排列的 TreeMap<Character,Integer> treeMap= new TreeMap<Character,Integer>(); for (int i = 0; i <arr.length ; i++) { //只要求存储英文字符。 if(arr[i]>='a'&&arr[i]<='z'||arr[i]>='A'&&arr[i]<='Z'){ if(!treeMap.containsKey(arr[i])){ treeMap.put(arr[i], 1); }else{ treeMap.put(arr[i],treeMap.get(arr[i])+1); } } } System.out.println("一共有"+treeMap.size()+"中英文字符"); Set<Map.Entry<Character,Integer>> st = treeMap.entrySet(); Iterator<Map.Entry<Character, Integer>> it = st.iterator(); //创建List集合,存储Map.Entry元素,存储的是每个键值对值。 ArrayList<Map.Entry<Character,Integer>> list= new ArrayList<Map.Entry<Character,Integer>>(); while (it.hasNext()) { Map.Entry<Character, Integer> en = it.next(); list.add(en); } /*进行排序,按照Map.Entry的值大小来排序,使用Collections的排序功能,按照指定比较器来比较排序。*/ Collections.sort(list, new Comparator<Map.Entry<Character, Integer>>() { @Override public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) { // TODO Auto-generated method stub return o1.getValue()-o2.getValue(); } }); //遍历list集合 for (Entry<Character, Integer> entry : list){ System.out.print(entry.getKey()+":"+entry.getValue()+"\t"); } }
----------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流!
----------------------
详细请查看:http://edu.csdn.net
相关文章推荐
- 黑马程序员——Java之集合框架(一)
- 黑马程序员-5-java-Collection集合类知识串讲(4)-集合框架工具类Utilities
- 黑马程序员--java集合TreeSet
- 黑马程序员——java集合
- 黑马程序员 Java基础<七>---> 集合框架
- 黑马程序员java基础之集合Set中的TreeSet和泛型
- 黑马程序员_Java第17天知识总结_集合框架的工具类_Collections_Arrays_将数组变成list集合_集合变数组_高级for循环_可变参数
- 黑马程序员--Java学习日记之集合(map集合和collections类)
- 黑马程序员_java_集合总结(上)
- 黑马程序员_Java基础_集合框架1
- 黑马程序员________Java集合List和Set的原理应用学习笔记
- 黑马程序员-Java 集合框架(二)-Map、Collections、新特性
- 黑马程序员——JAVA集合
- 黑马程序员————Java集合详解剖析
- 黑马程序员-java基础-List集合的特有遍历功能
- 黑马程序员——java基础--集合
- 黑马程序员——Java基础——集合(三)
- 黑马程序员——java基础拾遗之集合框架(一) List 和 Set
- 黑马程序员---Java基础--15天(集合框架之二)
- 黑马程序员-java基础之集合Map集合,Collections,Arrays工具类