Java 集合概述
- Java 集合就像一种容器,可以把多个对象的引用放入容器中。
- Java 集合类可以用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组
- Java 集合可分为Set、List 和Map 三种体系
- Set:无序、不可重复的集合,set又是以map为底层实现
- List:有序,可重复的集合,list接口是以数组为底层实现,是有序的
- Map:具有映射关系的集合,key-value(键值对),map接口底层是hash函数,无序(不是随机)
- 在Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成Object 类型处理;从Java5 增加了泛型以后,Java 集合可以记住容器中对象的数据类型
Java 集合类
Collection 接口
-
Collection 接口是List、Set 和Queue 接口的父接口,该接口里定义的方法既可用于操作Set 集合,也可用于操作List 集合
类型 方法 boolean add(E e)
确保此集合包含指定的元素(可选操作)。boolean addAll(Collection<? extends E> c)
将指定集合中的所有元素添加到此集合(可选操作)。void clear()
从此集合中删除所有元素(可选操作)。boolean contains(Object o)
如果此集合包含指定的元素,则返回true
。boolean containsAll(Collection<?> c)
如果此集合包含指定集合
中的所有元素,则返回true。boolean equals(Object o)
将指定的对象与此集合进行比较以获得相等性。int hashCode()
返回此集合的哈希码值。boolean isEmpty()
如果此集合不包含元素,则返回true
。Iterator iterator()
返回此集合中的元素的迭代器。int size()
返回此集合中的元素数。boolean remove(Object o)
从该集合中删除指定元素的单个实例(如果存在)(可选操作)。boolean removeAll(Collection<?> c)
删除指定集合中包含的所有此集合的元素(可选操作)。boolean default removeIf(Predicate<? super E> filter)
删除满足给定谓词的此集合的所有元素。boolean retainAll(Collection<?> c)
仅保留此集合中包含在指定集合中的元素(可选操作)。object toArray()
返回一个包含此集合中所有元素的数组
使用Iterator接口遍历集合元素
-
Iterator接口主要用于遍历Collection 集合中的元素,Iterator对象也被称为迭代器。
-
Iterator 接口隐藏了各种Collection 实现类的底层细节,向应用程序提供了遍历Collection 集合元素的统一编程接口。
-
Iterator仅用于遍历集合,Iterator本身并不提供存放对象的能力。如果需要创建Iterator对象,则必须有一个被迭代的集合。
类型 方法 boolean hasNext()
如果迭代具有更多元素,则返回true
。E next()
返回迭代中的下一个元素。void remove()
从底层集合中删除此迭代器返回的最后一个元素(可选操作)。
使用foreach循环遍历集合元素
- 从Java 5 开始,JDK提供了foreach循环迭代访问Collection
List
- List 代表一个元素有序、且可重复的集合,集合中的每个元素都有其对应的顺序索引
- List 允许使用重复元素,可以通过索引来访问指定位置的集合元素。
- List 默认按元素的添加顺序设置元素的索引。
- List 集合里添加了一些根据索引来操作集合元素的方法
- void add(intindex, Object ele)
- booleanaddAll(intindex, Collection eles)
- Object get(intindex)
- intindexOf(Object obj)
- intlastIndexOf(Object obj)
- Object remove(intindex)
- Object set(intindex, Object ele)
/**
*把数组转化为ArrayList
*或把ArrayList转化数组
*Arrays是数组的工具类
*/
@Test
public void test2() {
// 空容器(ArrayList),遍历数组并赋值
List list = new ArrayList();
//把list转换为数组
list.toArray();
int[] a = new int[2];
int[] b = new int[]{3, 5, 8};
int[] c = {6, 4, 8, 9};
list = Arrays.asList(b, c);
System.out.println(list);
sumArray(0,1,2,3,4,5,6,7,8,9);
sumArrsy(0,b);
}
//两个sumArray方法效果等同
public void sumArray(int sum,int... args) {
for (int i = 0; i < args.length; i++) {
sum += args[i];
}
System.out.println(sum);
}
public void sumArrsy(int sum, int[] args) {
for (int i = 0; i < args.length; i++) {
sum += args[i];
}
System.out.println(sum);
}
ArrayList
- ArrayList是List 接口的典型实现类
- 本质上,ArrayList是对象引用的一个变长数组
- 遍历元素和随机访问元素的效率比较高
- 插入、删除等操作频繁时性能低下
ArrayList常用方法
LinkedList
- LinkedList类采用链表存储方式。插入、删除元素时效率比较高
- 查找效率较低
LinkedList常用方法
public void test3() {
// 创建一个连续可变长度的数组
List list = new ArrayList();
list.add(1);
list.add("abc");
// 通过指定位置获取元素
System.out.println(list.get(0));
LinkedList<Integer> linkedList = new LinkedList<>();
linkedList.add(123);
linkedList.add(456);
System.out.println(linkedList.get(0));
//在集合头部插入指定元素
linkedList.addFirst(254);
System.out.println(linkedList.indexOf(456));
for (Integer integer : linkedList) {
System.out.println(integer);
}
}
Set
- Set接口存储一组唯一,无序的对象。
- HashSet 是Set接口常用的实现类。
- HashSet允许集合元素值为null
- 操作数据的方法与List类似,Set接口不存在get()方法。
- Iterator接口表示对集合进行迭代的迭代器,专门实现集合的遍历。
- 方法:
- hasNext():判断是否存在另一个可访问的元素
- next():返回要访问的下一个元素
/**
* 迭代器的使用,遍历集合框架
*/
@Test
public void test5() {
List<Person> perList = new ArrayList<Person>();
Person p1 = new Person();
p1.setName("张三");
p1.setAge(21);
Person p2 = new Person();
p2.setName("李四");
p2.setAge(20);
Person p3 = new Person();
p3.setName("王五");
p3.setAge(23);
perList.add(p1);
perList.add(p3);
perList.add(p2);
//获取迭代器
Iterator<Person> iterator = perList.iterator();
//1、两个方法效果等同
for (int i = 0; i < perList.size(); i++) {
System.out.print(perList.get(i).getName()+" ");
}
System.out.println();
//2、hasNext next
while (iterator.hasNext()) {
Person p = iterator.next();
System.out.print(p.getName()+" ");
}
Map
- HashMap是Map接口中最常见的实现类。
- 存储一组成对的键-值对象,提供key(键)到value(值)的映射,通过key来索引
- key不允许重复
- value允许重复
- 添加的对象将转换为Object类型
Map接口常用方法
-
添加、删除操作:
➢Object put(Object key,Objectvalue)
➢Object remove(Object key)
➢void putAll(Map t)
➢void clear()
-
元视图操作的方法:
➢Set keySet()
➢Collection values()
➢Set entrySet()
-
元素查询的操作:
➢Object get(Object key)
➢booleancontainsKey(Object key)
➢booleancontainsValue(Object value)
➢intsize()
➢booleanisEmpty()
➢booleanequals(Object obj)
/**
* * map接口
* * 1、存放key-value数据
* * key:不可以重复(底层使用的set)
* * value:可以重复的。底层使用的collection接口。
* * 2、实现类:
* * HashMap
* * LinkedHashMap
* * TreeMap
* * HashTale (不在使用)线程安全的容器
* * Properties子类,做键值对文件读取。
* * 3、常用方法;
* * put(key,value)
* * get(key);返回Object
* * size();
* *
* * keySet(); 返回一个 Set容器,含义:获取所有的key。
* * values();
*/
@Test
public void test6() {
HashMap<Integer, Object> map = new HashMap<>();
for (int i = 0; i < 100; i++) {
map.put(i, "Name" + i);
}
//遍历 keySet
/*Set<Integer> keySet = map.keySet();
for (Integer tmp : keySet) {
String value = (String) map.get(tmp);
System.out.println(value);
}*/
HashMap<String, Object> perMap = new HashMap<>();
perMap.put("age", 21);
perMap.put("name", "张三");
//遍历 values
Collection<Object> values = perMap.values();
Iterator<Object> iterator = values.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
/*for (Object value : values) {
System.out.println(value);
}*/
//遍历 entrySet,把map中每一个键值对封装到Set<Entry>
Set<Map.Entry<String, Object>> entrySet = perMap.entrySet();
for (Map.Entry<String, Object> entry : entrySet) {
String key = entry.getKey(); //获取key
Object value = entry.getValue(); //获取value
System.out.println(key+":"+value);
}
HashMap & Hashtable
- HashMap和Hashtable都是Map 接口的实现类
- 区别:
- Hashtable是一个古老的Map 实现类,不建议使用
- Hashtable是一个线程安全的Map 实现,但HashMap是线程不安全的。
- Hashtable不允许使用null 作为key 和value,而HashMap可以
- 与HashSet集合一样,Hashtable、HashMap也不能保证其中key-value 对的顺序
- Hashtable、HashMap判断两个Key 相等的标准是:两个Key 的hashCode值相等,并且equals 方法返回true。
- Hashtable、HashMap判断两个Value相等的标准是:两个Value 通过equals 方法返回true
TreeMap
- TreeMap存储Key-Value 对时,需要根据Key 对key-value 对进行排序。TreeMap可以保证所有的Key-Value 对处于有序状态。
- TreeMap的Key 的排序:
- 自然排序
- 定制排序
public void test7() {
//自然排序
TreeMap<Integer, Object> treeMap = new TreeMap<>();
treeMap.put(3, "a");
treeMap.put(5, "b");
treeMap.put(1, "c");
for (Integer key : treeMap.keySet()) {
System.out.println(treeMap.get(key));
}
//定制排序
Map<String,Object> tmap = new TreeMap<String,Object>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//自定义
return 0;
}
});
tmap.put("b", "b");
tmap.put("a", "a");
tmap.put("c", "c");
for (String s : tmap.keySet()) {
System.out.println(tmap.get(s));
}
}
Properties
- Properties 类是Hashtable的子类,该对象用于处理属性文件
- 由于属性文件里的key、value 都是字符串类型,所以Properties 里的key 和value 都是字符串类型
Collections
- Collections 是一个操作Set、List和Map 等集合的工具类
- Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
- 排序操作:(均为static方法)
- reverse(List):反转List 中元素的顺序
- shuffle(List):对List集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定List 集合元素按升序排序
- sort(List,Comparator):根据指定的Comparator 产生的顺序对List 集合元素进行排序
- swap(List,int,int):将指定list 集合中的i处元素和j 处元素进行交换
- Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
- Object max(Collection,Comparator):根据Comparator 指定的顺序,返回给定集合中的最大元素
- Object min(Collection)
- Object min(Collection,Comparator)
- int frequency(Collection,Object):返回指定集合中指定元素的出现次数
- void copy(List dest,Listsrc):将src中的内容复制到dest中
- booleanreplaceAll(List list,Object oldVal,Object newVal):使用新值替换List 对象的所有旧值
public void test1() {
ArrayList<String> list = new ArrayList<>();
list.add("tom");
list.add("jack");
list.add("tom");
list.add("jone");
//Collections 反转元素顺序
Collections.reverse(list);
System.out.println(list);
//shuffle 随机排序
Collections.shuffle(list);
System.out.println(list);
//sort 排序
Collections.sort(list);
System.out.println(list);
//swap 交换
Collections.swap(list, 1, 3);
System.out.println(list);
//frequency 获取元素出现次数
int count = Collections.frequency(list, "tom");
System.out.println(count);
ArrayList<Person> people = new ArrayList<>();
Person p1 = new Person();
p1.setName("张三");
p1.setAge(21);
Person p2 = new Person();
p2.setName("李四");
p2.setAge(20);
Person p3 = new Person();
p3.setName("张三");
p3.setAge(21);
people.add(p1);
people.add(p3);
people.add(p2);
//反转
Collections.reverse(people);
System.out.println(people);
for (Person person : people) {
System.out.print(person.getName()+" ");
}
//随机排序
Collections.shuffle(people);
for (Person person : people) {
System.out.print(person.getName()+" ");
}
泛型
1、什么是泛型
泛型,JDK1.5新加入的,解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或实例化时只要指定好需要的具体的类型即可。
Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。
只有指定类型才可以添加到集合中:类型安全 ,读取出来的对象不需要强转:便捷
2、泛型的声明
interface List 和class Test<K,V> 其中,T,K,V不代表值,而是表示类型。这里使用任意字母都可以。常用T表示,是Type的缩写。
3、泛型的实例化
一定要在类名后面指定类型参数的值(类型)。如:
List strList= new ArrayList();
Iterator iterator = customers.iterator();