# 集合存储结构
**集合和数组的区别**
**1. 数组能容纳基本数据类型和引用数据类型;集合只接收引用数据类型。
2. 数组的长度是固定的。【集合长度可变的。】
3. 数组可进行的操作很有限:
4. 集合是对象,有方法和属性可供调用,功能丰富了;面向对象的特性,封装,继承,多态。**
## 1.Collection接口
Collection接口中的方法
add(Objectionn o)添加一个元素
size() 元素的个数
addAll(Collection<? extends E> c) 添加一个集合对象的元素
contains(Object o) 是否包含该"o"元素
isEmpty() 是否为空
iterator() 迭代
remove(Object o) 删除对象
toArray() 返回数组
## 2. List接口
List集合中的元素都是有序可重复的集合
List接口中的方法
void add(int index, Object ele) //指定下标添加元素
boolean addAll(int index, Collection eles) //指定下标添加集合
Object get(int index) //获取下标的元素
int indexOf(Object obj) //从左到右获取元素的下标
int lastIndexOf(Object obj) //从右到左获取元素的下标(永远从0开始的)
Object remove(int index) //通过下标删除
Object set(int index, Object ele) //修改下标的元素
List subList(int fromIndex, int toIndex) //返回一个子集合(不包含toIndex下标)
**2.1、ArrayList**
有序,不唯一;有序是索引顺序;
*(1)遍历时按添加顺序;
*(2)内存原理:内存中分配的是连续的空间;有索引,
* ArrayList是一个Object类型的数组;数组长度不够了,会生成更长的新数组;
*(3)性能:按索引查询,效率高;
* 按内容查询,效率低;
* 添加删除元素效率低;可能引起大量元素的位移;
/*
*ArrayList的遍历方法:
*1.for-each;
*2.普通for循环;操作索引;
*3.迭代器:
* 1)生成迭代器:Iterator it=list.iterator();//it初始位置在索引为0的元素之前;
* 2)it.hasNext():以it当前位置为参照,还有下一个元素吗?
* 3) it.next():先把it当前位置的下一个元素取出来;把it的位置往后移动一个元素;
* 4)it.remove():把it当前位置的元素删除。
* 5)在用迭代器遍历集合期间,不要用集合对象名对集合进行操作(如list.add(6)),会出现并发修改异常:java.util.ConcurrentModificationException。
```
public class Test2 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// 集合的遍历;for-each;
// for (Object obj : list) {
// System.out.println(obj.toString());
// }
//普通的for循环;
// for(int i=0;i<list.size();i++){
// Object obj=list.get(i);
// System.out.println(obj);
// }
Iterator it=list.iterator();
while(it.hasNext()){
Object obj=it.next();//把it原有位置的下一个元素取出来;把it的位置往后移动一个元素;
System.out.println(obj);
//list.add(6);会出现并发修改异常:java.util.ConcurrentModificationException。
it.remove();//it指向的是哪个元素,就删除哪个元素;
}
System.out.println(list.size());
}
}
```
**2.2 LinkList**
.链表:LinkedList,物理空间上不连续,但逻辑上是连续的。
添加删除元素效率高;不会引起大量元素的位移;
*LinkedList的特点:有序,不唯一;有序是索引顺序;
*(1)遍历时按添加顺序;
*(2)内存原理:链表
*(3)性能:按索引查询,效率低;必须从第一个元素查起;
* 按内容查询,效率低;
* 添加删除元素效率高;不会引起大量元素的位移;
1.for-each;
2.普通for循环;操作索引;
3.迭代器:
```
public class Test {
public static void main(String[] args) {
// 创建一个容器对象;
List list = new LinkedList();// 运用多态;
List subList = new LinkedList();
subList.add(1);
subList.add(2);
// 添加;
Person p1 = new Person();
Person p2 = new Person();
// add(Object obj):Object做形参,可以接收不同的子类实参;运用多态;
list.add(p1);
list.add(p2);
list.add("Hello");
// 123--->Object obj=new Integer(123);添加数字相当于自动装箱;
list.add(123);
list.add(2, "java");
list.addAll(subList);
list.addAll(2, subList);
// 删除;
// list.remove(2);//2是索引位置;
// list.remove("java");//如果有多个"java",就删除第一个;
// list.remove(new Integer(2));
// list.removeAll(subList);//删除的是所有和subList里相同的元素,删除的是与subList的交集;
// 改;
list.set(1, "today is perfect");
// list.clear();
//list.retainAll(subList);// 取与subList交集;
// 查;
System.out.println(list.size());// 实际元素的个数,不是集合的总容量;
// System.out.println(list.get(0));//得到索引为0的位置的元素;
System.out.println(list.contains(p1));
System.out.println(list.isEmpty());
// 集合的遍历;
for (Object obj : list) {
System.out.println(obj.toString());
}
// 普通的for循环;
for (int i = 0; i < list.size(); i++) {
Object obj = list.get(i);
System.out.println(obj);
}
Iterator it = list.iterator();
while (it.hasNext()) {
Object obj = it.next();// 把it原有位置的下一个元素取出来;把it的位置往后移动一个元素;
System.out.println(obj);
// list.add(6);会出现并发修改异常:java.util.ConcurrentModificationException。
it.remove();// it指向的是哪个元素,就删除哪个元素;
}
System.out.println(list.size());
}
}
```
## 3.Set接口
Set接口 元素无序(hashCode())、不可重复的集合
HashSet LinkedHashSet TreeSet
1)HashSet 无序(hashCode())、不可重复的集合 hashCode() equals()
*HashSet的特点:无序,唯一;
*(1)遍历是不可预知顺序;
*(2)内存原理:哈希表,用hashcode和equals()方法;
*(3)性能:查询效率高;
* 添加删除效率高;
*(4)自定义类,建议重写hashcode()和equals()方法,成对重写。
* 告诉程序你的比较策略。
* 不重写,就用Object的方法了。
1. HashSet怎么保证元素的唯一性呢?
*先用hashcode计算出地址,如果没有元素,就存进去;如果已有元素,就用equals(),如果true,不添加了;
*如果false,就添加。
*
*hashcode相同,元素不一定相同;再用equals(),true才是相同的。
*hashcode不同,元素一定不同。
2.遍历:
* 1)for-each:
* 2)迭代器:Iterator it=set.iterator();
*
*3.添加:
* set.add(Object obj);
* set.addAll();
*
* 删除:
* set.remove(Object obj);
* set.removeAll();
*
* 查:
* set.isEmpty();
* set.size();
* set.clear();
* set.contains();
* set.containsAll();
* set.retainAll();
*
* 转换:
* //把集合类型转成Object类型的数组;
Object[] objArr=set.toArray();
*
* */
```
public class TestHashSet {
public static void main(String[] args) {
//创建一个HashSet对象;
Set set=new HashSet();
//添加;
System.out.println(set.add(23));//true;
set.add(36);
set.add(48);
set.add(77);
set.add(86);
set.add(67);
set.add(76);
System.out.println(set.add(23));//false;
set.add(56);
set.add(78);
set.add(47);
//删除;
set.remove(47);
//改;
//查;
System.out.println(set.size());
System.out.println(set.isEmpty());
//set.clear();
//遍历;
Iterator it=set.iterator();
while(it.hasNext()){
Object obj=it.next();
System.out.println(obj);
}
System.out.println("==========================");
//用for-each遍历;
for(Object obj:set){
System.out.println(obj.toString());
}
//把集合类型转成Object类型的数组;
Object[] objArr=set.toArray();
System.out.println(Arrays.toString(objArr));
}
}
```
2)LinkedHashSet:遍历输出的内容和添加的顺序一致
3)TreeSet
* 1.添加元素必须是同一类型,否则遍历出错
* 2.遍历输出顺序按默认顺序(从小到大)如:String,Integer等
* 3.自然排序,必须要实现Comparable,compareTo方法,实现排序
* 4.定制排序,需要实现接口Comparator接口
*TreeSet:有序,唯一;有序,不是添加顺序,是大小顺序;
*(1)遍历时是大小顺序;
*(2)内存原理:二叉树;
*(3)查询(按内容查询),效率中等;在ArrayList和HashSet之间;
* 添加删除,效率中等。
*(4)如果是自定义类,要实现Comparable接口;
* 告诉程序你的比较策略;
* 否则会报:java.lang.ClassCastException:Student--->Comparable;
*
* Set treeSet=new TreeSet();
*
*(5) 也可以实现Comparator接口;
```
* StuScoreComp sComp=new StuScoreComp();
Set treeSet = new TreeSet(sComp);
public class TestTreeSet {
public static void main(String[] args) {
//创建TreeSet对象;
Set treeSet=new TreeSet();
//添加;
treeSet.add(50);
treeSet.add(35);
treeSet.add(78);
treeSet.add(27);
treeSet.add(45);
treeSet.add(56);
treeSet.add(40);
treeSet.add(45);
treeSet.add(48);
treeSet.add(90);
//遍历;
Iterator it=treeSet.iterator();
while(it.hasNext()){
Object obj=it.next();
System.out.println(obj);
}
}
}
```
## 4.Map接口
*Map特有的三个方法:
*map.keySet();获取key的集合;
*map.values();获取value的集合;
*map.entrySet();获取key和value的集合;
Map接口 key-value对”的集合
HashMap(效率高) LinkedHashMap TreeMap HashTable(古老的类,基于线程安全,效率低)
Properties load(InputStream inStream) 从输入字节流读取属性列表(键和元素对)。
*HashMap:
*1.是键值对,每个元素包含两部分:key,value;
*2.key和value是一一对应的;
*3.key是无序,唯一的;如果添加了重复的key,不报错,后面的会覆盖前面的;
*4.value是无序,不唯一的;
*5.key和value都可以是null。
*6.如果key是自定义类:要重写hashCode()和equals()方法;
* 告诉程序你的比较策略;
内存原理:key部分与HashSet原理相同,无序,唯一;
事实上,HashSet底层调用的是HashMap.
/*
*HashMap底层是一个Entry类型的数组;
*Entry<Integer,String>:
*Entry:key,value和指向下一个Entry元素的引用。
*
*
```
*/
public class TestHashMap1 {
public static void main(String[] args) {
Map<Integer,String> map=new HashMap<Integer,String>();
map.put(1, "罗马假日");
map.put(3, "三国演义");
map.put(2, "炼金术士");
//遍历:
Set entrySet=map.entrySet();
Iterator<Entry<Integer,String>> it=entrySet.iterator();
while(it.hasNext()){
// it.next().getKey();
// it.next().getValue();
Entry entry=it.next();
System.out.println(entry);
}
}
}
```
/*
*TreeMap: 有序(大小顺序),唯一;按key排序;
*如果key是自定义类:要实现Comparable或Comparator接口;
*告诉程序你的比较策略;
*
*/
```
import java.util.TreeMap;
public class TestTreeMap {
public static void main(String[] args) {
Map<Integer,String> map=new TreeMap<Integer,String>();
map.put(16, "炼金术士");
map.put(2, "炼金术士");
map.put(1, "罗马假日");
map.put(3, "三国演义");
map.put(2, "围城");
//遍历:
Set entrySet=map.entrySet();
Iterator<Entry<Integer,String>> it=entrySet.iterator();
while(it.hasNext()){
Entry entry=it.next();
System.out.println(entry);
}
}
}
```
## 5.迭代器
迭代器:
* 1)生成迭代器:Iterator it=list.iterator();//it初始位置在索引为0的元素之前;
* 2)it.hasNext():以it当前位置为参照,还有下一个元素吗?
* 3) it.next():先把it当前位置的下一个元素取出来;把it的位置往后移动一个元素;
* 4)it.remove():把it当前位置的元素删除。
* 5)在用迭代器遍历集合期间,不要用集合对象名对集合进行操作(如list.add(6)),会出现并发修改异常:java.util.ConcurrentModificationException。
list.iterator():
(1) iterator()不是Collection自己的方法,是继承自接口Iterable;
(2) Iterator iterator();返回值是Iterator类型的;
(3) Iterator: 是一个接口类型,它里面的三个方法:hasNext();
next();
remove();
(4)遍历[集合]时底层调用Iterator完成操作。
## 6.Collectiongons工具类
/*
*1.Collections:
* 1)和Arrays一样,是专门用来操作集合的工具类;
* 2)大部分方法 都是静态的,可以通过类名直接调用;
* 3)构造方法私有化,不能创建Collections的对象;
*
*2.Collections的常用方法:
* 1)Collections.addAll(list,60,50);
* //如果是自定义对象,要给出比较策略,实现Comparable接口;
* 2)Collections.sort(list);
* //用于排好序的集合上;查到就返回索引值,没查到就返回-(应该在的位置+1);
* 3)int index=Collections.binarySearch(list, 67);
* 4)Collections.copy(list, list2);
* 5)int max=Collections.max(list);
6)int min=Collections.min(list);
7)Collections.fill(list, 888);
8)Collections.reverse(list);
* 9)List list3 = Collections.synchronizedList(list);
*
*3.Collection和Collections的区别:
* 1)Collection是Java提供的集合接口,存储一组不唯一,无序的对象。它有两个子接口List和Set。
2)Java中还有一个Collections类,专门用来操作集合类 ,它提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
*/
```
public class TestCollections {
public static void main(String[] args) {
ArrayList list=new ArrayList();
//添加Integer类型的元素;
list.add(3);
list.add(4);
list.add(1);
list.add(2);
list.add(5);
Collections.addAll(list,60,50);
//Collections.sort(list);
//int index=Collections.binarySearch(list, 50);
ArrayList list2=new ArrayList();
Collections.addAll(list2,11,12,13,14);
Collections.copy(list, list2);
//Collections.fill(list, 888);
//Collections.reverse(list);
int max=Collections.max(list);
int min=Collections.min(list);
System.out.println(max+" "+min);
//System.out.println(index);
//遍历:
Iterator it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//ArrayList是线程非同步,程序员可以自己写代码把ArrayList转成同步的操作;
List list3 = Collections.synchronizedList(list);
}
}
```