一、概念
1.数学中:
集合:指具有某种特定性质的具体的或抽象的对象汇总而成的集体。其中构成集合的这些对象则称为该集合的元素 。
数组:所谓数组,是有序的元素序列。数组是用于储存多个相同类型数据的集合。
2.编程中:
集合类:负责保存、盛装程序创建的对象,因此集合类也被称为容器类;Java集合类存放于 java.util 包中;
数组:数组只能放统一类型的数据,而且一旦在数组初始化时指定了这个数组长度,这个数组长度就是不可变的;
3.注意:
①、集合只能存放对象。比如你存一个 int 型数据 1放入集合中,其实它是自动转换成 Integer类后存入的,Java中每一种基本类型都有对应的引用类型。
②、集合存放的是多个对象的引用,对象本身还是放在堆内存中。
③、集合可以存放不同类型,不限数量的数据类型。
二、集合类的框架
简要说明:
1.Iterator迭代器是遍历集合的接口;
2.Collection是一个对集合概念进行了高度抽象而来的接口,Collection包含了List(有序集合)和Set(无序集合)两大分支;
3.Map是一个映射接口,即key-value键值对;
4.Arrays和Collections,它们是操作数组、集合的两个工具类;
5.Comparable内比较器和Comparator外比较器;
三、框架详解
1.Iterator迭代器
方法:
Object next():返回迭代器刚越过的元素的引用,返回值是 Object,需要强制转换成自己需要的类型;
boolean hasNext():判断容器内是否还有可供访问的元素;
void remove():删除迭代器刚越过的元素;
void forEachRemaining(Consumer super E> action):对每个剩余元素执行给定的操作,直到所有元素都被处理或动作引发异常。
应用示例:
package com.jagger.iterator;
import java.util.ArrayList;
import java.util.Iterator;
public class Show {
public static void main(String[] args) {
ArrayList aa = new ArrayList();
aa.add("Zhao");
aa.add("Qian");
aa.add("Sun");
aa.add("Li");
System.out.println("Before Iterator:" + aa);
Iterator it = aa.iterator();
while(it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}
consoles输出结果:
Before Iterator:[Zhao, Qian, Sun, Li]
Zhao
Qian
Sun
Li
注意事项:
(1)Iterator只能单向移动。
(2)Iterator.remove()是唯一安全的方式来在迭代过程中修改集合;如果在迭代过程中以任何其它的方式修改了基本集合将会产生未知的行为。而且每调用一次next()方法,remove()方法只能被调用一次,如果违反这个规则将抛出一个并发修改异常。
2.Collection接口
方法:参考jdk
Collection接口有两个主要的子接口List和Set,注意Map不是Collection的子接口,以下进行介绍;
List接口
List接口继承于Collection接口,是一个允许重复的有序集合,这里所说的有序是指数据存取上的有序,可以通过类似于数组的索引来访问元素。实现List接口的主要有:ArrayList、LinkedList、Vector、Stack。
List接口的常用方法:
增:add(E); add(int index,E e);
删:remove(Object obj); remove(int index);
查:get(int index);
改:set(int index,E e);
其他:size(); clear(); toArray(); iterator(); isEmpty(); contains(object obj);
List接口的主要实现类:
(1)ArrayList
概念:ArrayList是一个动态数组,非同步;
特点:查询速度快,增删速度较慢,线程不安全;
方法:常用方法与list接口方法基本相同;
(2)LinkedList
概念:LinkedListd是一个双向链表,非同步;
特点:查询速度慢,增删速度较快,线程安全;
特点:相对于list接口常用方法中又增加了一些首尾操作的方法;
增:void addFirst(E e) ;void addLast(E e) ;
删:E removeFirst() ;E removeLast() ;
查:E getFirst() ;E getLast() ;
其他:E pop() ;弹出,等同于E removeFirst()
void push(E e) 推入,等同于void addFirst(E e);
package InterfaceList;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Show {
public static void main(String[] args) {
//创建一个LinkedList对象
LinkedList ll = new LinkedList();
String temp;
//增加元素
ll.addFirst("First");
ll.addFirst("Middle");
ll.addLast("Last");
ll.addLast("End");
System.out.println("增加后列表中的元素:" + ll);
//删除元素
temp = ll.removeFirst();
System.out.println("删除列表中的首位元素:" + temp);
temp = ll.removeLast();
System.out.println("删除列表中的末位元素:" + temp);
System.out.println("删除后列表中的元素:" + ll);
//获取元素
temp = ll.getFirst();
System.out.println("返回列表中的首位元素:" + temp);
temp = ll.getLast();
System.out.println("返回列表中的末位元素:" + temp);
//pop,push查看源码即可理解此方法
temp = ll.pop();
System.out.println("pop推出的元素:" + temp);
ll.push("new");
System.out.println("推入后列表中的元素:" + ll);
}
}
console结果:
增加后列表中的元素:[Middle, First, Last, End]
删除列表中的首位元素:Middle
删除列表中的末位元素:End
删除后列表中的元素:[First, Last]
返回列表中的首位元素:First
返回列表中的末位元素:Last
pop推出的元素:First
推入后列表中的元素:[new, Last]
(3)Vector
概念: Vector与ArrayList相似,但是Vector是同步的。
特点:与Arraylist相似(被其取代),但是线程安全;
方法:不做介绍,Vector已被ArrayList取代;
(4)Stack
概念:Stack继承自Vector,FILO栈。
Set接口的实现类:
(1)HashSet
概念: 底层采用哈希表结构;
特点:增删快,查找快,无序的,非同步,非线程安全,不允许元素重复,仅能够存入一个null值;
方法:
示例:
package InterfaceSet;
import java.util.HashSet;
import java.util.LinkedHashSet;
public class hashset {
public static void main(String[] args) {
//String的hash值,hashCode()方法可以查看源码理解
String s1 = new String("abc");
String s2 = new String("acD");
System.out.println(s1 + "\n" +s2);
System.out.println("abc的hash值:" + s1.hashCode() + "\n" + "acD的hash值:" + s2.hashCode());
//HashSet添加元素的过程
HashSet hs = new HashSet();//创建集合对象
hs.add("abc");//添加元素
System.out.println("1-" + hs.hashCode());//打印当前对象的hash值
hs.add("hello");
System.out.println("2-" + hs.hashCode());
hs.add("abc");//相同对象,无法添加到集合中
System.out.println("3-" + hs.hashCode());
hs.add("world");
System.out.println("4-" + hs.hashCode());
hs.add("acD");//字符串"acD"的hash值与字符串"abc"相同,因为源码h = key.hashCode(),比较的是添加的字符串的hash值
System.out.println("5-" + hs.hashCode());//此时打印出来的是hs集合对象的hash值
System.out.println(hs);//console结果可以看出HashSet集合的无序
//LinkedHashSet与HashSet的对比
LinkedHashSet lhs = new LinkedHashSet();
lhs.add("abc");
lhs.add("hello");
lhs.add("abc");//相同对象,无法添加到集合中
lhs.add("world");
lhs.add("acD");//
System.out.println(lhs);//console结果可以看出LinkedHashSet集合的有序
}
}
console结果:
abc
acD
abc的hash值:96354
acD的hash值:96354
1-96354
2-99258676
3-99258676
4-212577478
5-212673832
[abc, world, acD, hello]
[abc, hello, world, acD]
HashSet集合添加元素的过程:
1、当向HashSet集合中存入一个元素时,HashSet会先调用该对象的hashCode()方法来得到该对象的hash值,然后根据hash值决定该对象在HashSet中的存储位置;
1.1、如果 hash值不同,直接把该元素存储到 hashCode() 指定的位置;
1.2、如果 hash值相同,那么会继续判断该元素和集合对象的 equals() 作比较;
1.2.1、hash值相同,equals 为 true,则视为同一个对象,不保存在 hashSet()中;
1.2.2、hash值相同,equals 为 false,则存储在之前对象同槽位的链表上,这非常麻烦, 我们应该避免这种情况;
注意:
每个 对象都有HashCode方法(定义在Object类中),所以每个对象都可以获取其hash值;
Java中toString()方法获取到的不是实际内存地址(java设计中不允许直接操作内存地址),而是hash值得十六进制;
(2)LinkedHashSet
概念: 底层采用哈希表结构(决定元素的存储位置)+链表结构(维护元素的次序);
特点:增删快,查找快,非同步,有序的,非线程安全,不允许元素重复;
方法:LinkedHashSet继承自HashSet,方法基本相同;
(3)TreeSet
概念: 是一个有序集合,其底层是基于TreeMap实现的,非线程安全;
特点:TreeSet可以确保集合元素处于排序状态,支持两种排序方式:自然排序和定制排序,其中自然排
序为默认的排序方式;
方法:
3.Map接口
Map与List、Set接口不同,它是由一系列键值对(key-value)组成的集合,提供了key到Value的映射;
(1)HashMap
概念:
特点:
方法:
package InterfaceMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class hashmap {
public static void main(String[] args) {
//创建集合对象
HashMap hm = new HashMap();
//添加元素
hm.put("a", "admin");
hm.put("b", "boy");
hm.put("c", "cat");
hm.put("d", "dog");
hm.put("e", "eee");
System.out.println(hm);
String vv = hm.remove("e");
System.out.println("删除的元素值:" + vv);
//Map集合遍历第一种方法:
//利用Map的keySet() 方法获取键Key集合,Map中Key的集合就是Set集合
Set ss = hm.keySet();
//遍历Key的集合,来遍历Map集合的键值对;
Iterator its = ss.iterator();
while(its.hasNext()) {
//循环获取key值
String key1 = its.next();
//利用Map的get()方法,根据key值获取对应的value值
String value1 = hm.get(key1);
//打印键对值
System.out.println(key1 + "=" + value1);
}
System.out.println("\n");
//Map集合遍历第二种方法:
//利用Map的entrySet()获取键值对关系对象的Entry集合
Set> se = hm.entrySet();
//增强型for循环遍历:for(元素类型 ele : 集合名/Iterable 实例)
for(Map.Entry entry1 : se) {
String key2 = entry1.getKey();
String value2 = entry1.getValue();
System.out.println(key2 + "=" + value2);
}
System.out.println("\n");
//Iterator迭代器遍历
Iterator> ite = se.iterator();
while(ite.hasNext()) {
Map.Entry entry2 = ite.next();
String key3 = entry2 .getKey();
String value3 = entry2 .getValue();
System.out.println(key3 + "=" + value3);
}
}
}
console打印结果:
{a=admin, b=boy, c=cat, d=dog, e=eee}
删除的元素值:eee
a=admin
b=boy
c=cat
d=dog
a=admin
b=boy
c=cat
d=dog
a=admin
b=boy
c=cat
d=dog
(2)LinkedHashMap
(3)TreeMap
(4) Properties
概念: 是一个持久的属性集,是Map的一个实现类,Properties可以保存到流中或从流中加载, 属性列表中的每个键及其对应的值都是一个字符串;
特点:没有泛型(确定是String类型)
方法:
String getProperty(String key) //功能与Map的Get()方法相似
Object setProperty(String key, String value) //功能与Map的Put()方法相似
Set stringPropertyNames() //功能与Map的keySet()方法相似
void load(Reader reader) //
void store(Writer writer, String comments) //
Java可变参数:
package varable;
public class varable {
public static void main(String[] args) {
System.out.println(add1(1,3,5,7,9));
System.out.println(add2(2,4,6,8,10));
}
//使用foreach循环
public static int add1(int t,int ... arg) {
int sum = t;
for (int i : arg) {
sum += i;
}
return sum;
}
//传统的for循环方法
public static int add2(int t,int j,int ... arg) {
int sum = t+j;
int i = 0;
for(i = 0;i < arg.length;i++) {
sum += arg[i];
}
return sum;
}
}
概念:
Java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理 ;
特点:
1)可变参数只是参数的个数可以改变,参数类型必须相同不可改变;
2)可变参数只能使用在参数列表中的最后一项;
3)一个方法中只能有一个可变参数;
增强型foreach循环原理:
1、对于数组,foreach 循环实际上还是用的普通的 for 循环;
2、对于集合,foreach 循环实际上是用的 iterator 迭代器迭代;
3、因为 Map 集合即没有实现于 Collection 接口,也没有实现 Iterable 接口,所以不能对 Map 集合进行 for-each 遍历
4.Collections
概念: 集合工具类,此类仅由静态方法组合或返回集合;
特点:
方法: