Java集合
在Java 中数组的长度是不可修改的。然而在实际应用的很多情况下,无法确定数据数量。这些数据不适合使用数组来保存,这时候就需要使用集合。Java 的集合就像一个容器,用来存储 Java 类的对象。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。Java 所有的集合类都位于 java.util 包下,提供了一个表示和操作对象集合的统一构架,包含大量集合接口,以及这些接口的实现类和操作它们的算法。
Java集合框架
从上图中我们可以看出,Collection 接口包含list,set和Queue。Map接口是单独的一个接口。
接口实现类
Java 平台提供了许多数据集接口的实现类。List下有ArrayList,LinkedList,Vector。Set下有HashSet,LinkedHashSet,TreeSet。Map下有HashMap,LinkMap,TreeMap,Hashtable.
Collection接口
Collection 接口是 List 接口和 Set 接口的父接口,通常情况下不被直接使用。Collection 接口定义了一些通用的方法,通过这些方法可以实现对集合的基本操作。因为 List 接口和 Set 接口继承自 Collection 接口,所以也可以调用这些方法.
boolean add(E e) 向集合中添加一个元素,E 是元素的数据类型boolean addAll(Collection c) 向集合中添加集合 c 中的所有元素void clear() 删除集合中的所有元素boolean contains(Object o) 判断集合中是否存在指定元素boolean containsAll(Collection c) 判断集合中是否包含集合 c 中的所有元素boolean isEmpty() 判断集合是否为空Iteratoriterator() 返回一个 Iterator 对象,用于遍历集合中的元素boolean remove(Object o) 从集合中删除一个指定元素boolean removeAll(Collection c) 从集合中删除所有在集合 c 中出现的元素boolean retainAll(Collection c) 仅仅保留集合中所有在集合 c 中出现的元素int size() 返回集合中元素的个数Object[] toArray() 返回包含此集合中所有元素的数组
public static void main(Strmg[] args){ ArrayList list1=new ArrayList(); //创建集合 iist1 ArrayList list2=new ArrayList(); //创建集合 Iist2 list1.add("one"); //向 list1 添加一个元素 list1.add("two"); //向 list1 添加一个元素 list2.addAll(list1); //将 list1 的所有元素添加到 list2 list2.remove(0); //删除第一个元素 }
list集合
List :有序,可以重复的集合。List 接口实现了 Collection 接口,它主要有两个实现类:ArrayList 类和 LinkedList 类。因为是有序的,所以第一个添加到 List 集合中的元素的索引为 0,第二个为 1。
ArrayList:
ArrayList 类实现了可变数组的大小,存储在内的数据称为元素。它还提供了快速基于索引访问元素的方式,对尾部成员的增加和删除支持较好。使用 ArrayList 创建的集合,允许对集合中的元素进行快速的随机访问,不过,向 ArrayList 中插入与删除元素的速度相对较慢。
//创建ArrayListListlist = new ArrayList();list.add(2);//add新增值到list集合list.add(4);list.add(5);list.add(6);//获取list中第一个值 输出为2System.out.println(list.get(0));//获取2在列表的位置System.out.println(list.indexOf(2));//在指定的位置添加数值 第一个为下标,第二个为添加的值list.add(4, 7);//指定位置替换值 第一个为下标,第二个为添加的值list.set(4, 8);//将list中0-2的值提出Listlist1 = list.subList(0, 2);
LinkList类
LinkedList 类采用链表结构保存对象,这种结构的优点是便于向集合中插入或者删除元素。需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高,与ArrayList不同的是会按照字典自动排序。
void addFirst(E e) 将指定元素添加到此集合的开头void addLast(E e) 将指定元素添加到此集合的末尾E getFirst() 返回此集合的第一个元素E getLast() 返回此集合的最后一个元素E removeFirst() 删除此集合中的第一个元素E removeLast() 删除此集合中的最后一个元素
ArrayList 和LinkedList区别:
ArrayList是Array(动态数组)的数据结构,而LinkedList是Link(链表)的数据结构。随机访问(get和set)时,ArrayList优于LinkedList;新增和删除操作,LinedList比较占优势。
list集合的遍历:
List list = new ArrayList();list.add("11");list.add("22");list.add("33");System.out.println("--------------------");// 循环第一种方式 Iteratorfor (Iterator iterator = list.iterator(); iterator.hasNext();) {String string = (String) iterator.next();System.out.println(string);}System.out.println("--------------------");// 增强forfor (String string : list) {System.out.println(string);}System.out.println("--------------------");//for循环for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}
Set集合
Set 集合类似于一个罐子,程序可以依次把多个对象“丢进”Set 集合,而 Set 集合通常不能记住元素的添加顺序。也就是说 Set 集合中的对象不按特定的方式排序,只是简单地把对象加入集合。Set 集合中不能包含重复的对象,并且最多只允许包含一个 null 元素。因此不能通过下标获得对应的元素。
HashSet 类
HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时就是使用这个实现类。HashSet 是按照 Hash 算法来存储集合中的元素。因此具有很好的存取和查找性能。set比较值时需要重写equals和hashcode才可以。如果没有重写这两个方法,则无法保证元素的唯一性。
//set集合的构建Setset = new HashSet(); set.add("11");//添加元素11set.add("11");//再次添加元素11,会自动去重set.add(""); //允许null//获取集合的大小 System.out.println("集合大小为:"+set.size());
TreeSet:
TreeSet 类同时实现了 Set 接口和 SortedSet 接口。SortedSet 接口是
Set 接口的子接口,可以实现对集合进行自然排序,因此使用 TreeSet 类实现的 Set 接口默认情况下是自然排序的,这里的自然排序指的是升序排序。E first() 返回此集合中的第一个元素。其中,E 表示集合中元素的数据 类型E last() 返回此集合中的最后一个元素E poolFirst() 获取并移除此集合中的第一个元素E poolLast() 获取并移除此集合中的最后一个元素SortedSet subSet(E fromElement,E toElement) 返回一个新的集合,新集合包含原集合中 fromElement 对象与 toElement对象之间的所有对象。包含 fromElemen t对象,不包含 toElement 对象SortedSet headSet不包含 toElement 对象SortedSet tailSet(E fromElement) 返回一个新的集合,新集合包含原集合中 fromElement 对象之后的所有对象。包含 fromElement 对象
for循环:
public static void main(String[] args) {//set集合的构建Setset = new HashSet();set.add("11");//添加元素11set.add("11");//再次添加元素11,会自动去重set.add(""); //允许null//获取集合的大小 System.out.println("集合大小为:"+set.size());//for循环遍历集合for (String string : set) {System.out.println("【"+string+"】");}//iterator迭代器for (Iterator iterator = set.iterator(); iterator.hasNext();) {String string = (String) iterator.next();System.out.println("【"+string+"】");}}
Map
Map 是一种键-值对(key-value)集合,Map 集合中的每一个元素都包含一个键(key)对象和一个值(value)对象。用于保存具有映射关系的数据。
Map 集合里保存着两组值,一组值用于保存 Map 里的 key,另外一组值用于保存 Map 里的 value,key 和 value 都可以是任何引用类型的数据。Map 的 key 不允许重复,value 可以重复,即同一个 Map 对象的任何两个 key 通过 equals 方法比较总是返回 false。
Map 中的 key 和 value 之间存在单向一对一关系,即通过指定的 key,总能找到唯一的、确定的 value。从 Map 中取出数据时,只要给出指定的 key,就可以取出对应的 value。
HashMap
Map 主要用于存储键(key)值(value)对,根据键得到值,因此键不允许重复,但允许值重复。
HashMap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。
HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;
HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
HashMap基于哈希表结构实现的 ,当一个对象被当作键时,必须重写hasCode和equals方法。
LinkedHashMap
LinkedHashMap继承自HashMap,它主要是用链表实现来扩展HashMap类,HashMap中条目是没有顺序的,但是在LinkedHashMap中元素既可以按照它们插入图的顺序排序,也可以按它们最后一次被访问的顺序排序。
TreeMap
TreeMap基于红黑树数据结构的实现,键值可以使用Comparable或Comparator接口来排序。TreeMap继承自AbstractMap,同时实现了接口NavigableMap,而接口NavigableMap则继承自SortedMap。SortedMap是Map的子接口,使用它可以确保图中的条目是排好序的。
在实际使用中,如果更新图时不需要保持图中元素的顺序,就使用HashMap,如果需要保持图中元素的插入顺序或者访问顺序,就使用LinkedHashMap,如果需要使图按照键值排序,就使用TreeMap。
map常用的接口方法:
map的遍历:
public class Test { public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); map.put("1", "张三"); map.put("2", "李四"); map.put("3", "王五"); map.put("4", "孙九"); // 第一种:通过Map.keySet遍历key和value for (String key : map.keySet()) { System.out.println("key= " + key + " and value= " + map.get(key)); } // 第二种:通过Map.entrySet使用iterator遍历key和value System.out.println("===================通过Map.entrySet使用iterator遍历key和value:==================="); Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, String> entry = it.next(); System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue()); } // 第三种:通过Map.entrySet遍历key和value System.out.println("===================通过Map.entrySet遍历key和value:==================="); for (Map.Entry<String, String> entry : map.entrySet()) { System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue()); } // 第四种:通过Map.values()遍历所有的value,但是不能遍历键key System.out.println("===================通过Map.values()遍历所有的value:==================="); for (String v : map.values()) { System.out.println("value= " + v); } } }
泛型
泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率。
泛型集合:
泛型本质上是提供类型的“类型参数”,也就是参数化类型。我们可以为类、接口或方法指定一个类型参数,通过这个参数限制操作的数据类型,从而保证类型转换的绝对安全。
public class Person{ private String name; public Person(String _name) { this.name=_name; }}Map persons=new HashMap(); //定义泛型 Map 集合persons.put(1,new Person("HelloWorld"));
Map persons =new HashMap();”创建了一个键类型为 Integer、值类型为 Person 的泛型集合,即指明了该 Map 集合中存放的键必须是 Integer 类型、值必须为 Person 类型,否则编译出错。
Person preson = persons.get(0);//在获取 Map 集合中的元素时,不需要将"persons.get(id);"获取的值强制转换为 Person 类型,程序会隐式转换。
枚举
枚举是一个被命名的整型常数的集合,用于声明一组带标识符的常数。
声明枚举
声明枚举时必须使用 enum 关键字,然后定义枚举的名称、可访问性、基础类型和成员等。枚举声明的语法如下:
enum-modifiers enum enumname:enum-base { enum-body,}
enum-modifiers 表示枚举的修饰符主要包括 public、private 和 internal;enumname 表示声明的枚举名称;enum-base 表示基础类型;enum-body 表示枚举的成员,它是枚举类型的命名常数。
public enum SexEnum { male,female;}public enum Color { RED,BLUE,GREEN,BLACK;}
Java 中的每一个枚举都继承自 java.lang.Enum 类。当定义一个枚举类型时,每一个枚举类型成员都可以看作是 Enum 类的实例,这些枚举成员默认都被 final、public, static 修饰,当使用枚举类型成员时,直接使用枚举名称调用成员即可。
增加枚举方法:
enum WeekDay { Mon("Monday"),Tue("Tuesday"),Wed("Wednesday"),Thu("Thursday"),Fri("Friday"),Sat("Saturday"),Sun("Sunday"); // 以上是枚举的成员,必须先定义,而且使用分号结束 private final String day; private WeekDay(String day) { this.day = day; } public static void printDay(int i) { switch(i) { case 1: System.out.println(WeekDay.Mon); break; case 2: System.out.println(WeekDay.Tue); break; case 3: System.out.println(WeekDay.Wed); break; case 4: System.out.println(WeekDay.Thu); break; case 5: System.out.println(WeekDay.Fri); break; case 6: System.out.println(WeekDay.Sat); break; case 7: System.out.println(WeekDay.Sun); break; default: System.out.println("wrong number!"); } } public String getDay() { return day; }}