单列LIst集合
单列列表集合:
- 集合的由来
长度是固定的,当添加的元素超过了多个的长度时需要对分段重新定义,太麻烦了,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,通过元素的增加而增加,通过元素的减少而减少
副本和集合的区别:
区别1:
#数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但在存储的时候会自动装箱变成对象
区别2:
分布长度是固定的,不能自动增长*集合的长度的是可变的,可以根据元素的增加而增长1 2 3 C:复制和集合什么时候用
数组和集合什么时候用:
如果元素个数是固定的推荐用堆叠
如果元素个数不是固定的推荐用集合
Collection集合的基本功能用法
public static void main(String[] args) {
Collection c = new ArrayList(); //创建集合对象
c.add("a"); //添加元素,返回值为boolean
c.remove("a"); //删除元素,返回值为boolean
c.clear(); //清空集合,无返回值
boolean pd = c.contains("a"); //判断是否包含元素,包含则返回true
boolean pd = c.isEmpty(); //判断集合是否为空,为空返回true
int num = c.size(); //获取集合中元素的个数,返回值为int
}
Collection集合的带All功能用法
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
Collection c2 = new ArrayList();
c2.addAll(c1); //c1全部赋值给c2集合
c1.removeAll(c2); //删除c1内与c2交集的部分,返回值为boolean
boolean b = c1.containsAll(c2);//判断调用的集合是否包含传入的集合
boolean c = c1.retainAll(c2);//取c1和c2的交集,存入c1
//如果调用的集合改变就返回true,注意:如果c2无值则c1也将变为无值
System.out.println(c1);
System.out.println(c2);
}
集合的遍历之集合转数组遍历
public static void main(String[] args) {
Collection c = new ArrayList(); //创建集合对象
c.add("a");
c.add("b");
c.add(new Student("王欢", 28)); //创建对象存入数组
Object[] arr = c.toArray(); //将集合转换为数组
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
集合的遍历之迭代器遍历
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
Iterator it = c1.iterator();//获取c1集合的迭代器
while (it.hasNext()) { //判断集合中是否有元素
System.out.println(it.next()); //获取元素
}
Collection c2 = new ArrayList();
c2.add(new Student("张三", 23));
c2.add(new Student("李四", 18));
Iterator it2 = c2.iterator();//获取c2集合的迭代器
while (it2.hasNext()) {
Student s = (Student)it2.next(); //向下转型
System.out.println(s.getName());
}
}
List集合的特有功能
public static void main(String[] args) {
List c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
c1.add(1, "e");//指定索引位置添加元素
Object obj = c1.remove(1);//通过索引删除元素并返回删除的元素
Object obj2 = c1.get(0); //通过索引获取指定元素
c1.set(0, "z"); //将指定位置的元素修改
System.out.println(obj2);
System.out.println(c1);
}
List集合特有迭代器
该迭代器可以在遍历的同时向集合内添加元素
public static void main(String[] args) {
List c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("nan");
c1.add("c");
c1.add("d");
ListIterator it = c1.listIterator();//List集合特有迭代器
while (it.hasNext()) {
String str = (String) it.next();
if ("nan".equals(str)) { //当集合中存在nan时则添加元素
it.add("zzzzzzz"); //通过迭代器添加元素
}
}
System.out.println(c1);
}
Vector的特有功能概述和测试【注意:Vector已被完全替代,请勿再使用】
public static void main(String[] args) {
Vector v = new Vector();
v.addElement("a");
v.addElement("b");
v.addElement("c");
v.addElement("d");
Enumeration en = v.elements();//获取枚举
while (en.hasMoreElements()) {//判断集合中是否有元素
System.out.println(en.nextElement());//获取集合中的元素
}
}
List的三个子类的特点
ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
Vector相对ArrayList查询慢(线程安全的)
Vector相对LinkedList增删慢(数组结构)
LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
Vector和ArrayList的区别
Vector是线程安全的,效率低
ArrayList是线程不安全的,效率高
共同点:都是数组实现的
ArrayList和LinkedList的区别
ArrayList底层是数组结果,查询和修改快
LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
共同点:都是线程不安全的
注意:线程不安全可以通过工具类改为安全的
如何选择:
查询多用ArrayList
增删多用LinkedList
如果都多ArrayList
#### 案例:ArrayList去除集合中字符串的重复值
```java
public class CeShi {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
ArrayList abc = JiHeFF(list);
System.out.println(abc);
}
public static ArrayList JiHeFF(ArrayList list) {
ArrayList newList = new ArrayList(); //创建一个新集合
Iterator it = list.iterator(); //获取迭代器
while (it.hasNext()) { //判断老集合中是否有元素,遍历老集合
Object obj = it.next(); //将每一个元素临时记录住
if (!newList.contains(obj)) { //如果新集合中不包含该元素
newList.add(obj); //将该元素添加到新集合中
}
}
return newList; //将新集合返回
}
}
案例:ArrayList去除集合重复自定义对象元素
注意:需要重写类的equals()方法
public class CeShi {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Student("张三", 23));
list.add(new Student("张三", 23));
list.add(new Student("李四", 23));
list.add(new Student("李四", 23));
list.add(new Student("李四", 23));
ArrayList newList = JiHeFF(list);
System.out.println(newList);
}
public static ArrayList JiHeFF(ArrayList list) {
ArrayList newList = new ArrayList(); //创建一个新集合
Iterator it = list.iterator(); //获取迭代器
while (it.hasNext()) { //判断老集合中是否有元素,遍历老集合
Object obj = it.next(); //将每一个元素临时记录住
if (!newList.contains(obj)) { //如果新集合中不包含该元素
newList.add(obj); //将该元素添加到新集合中
}
}
return newList; //将新集合返回
}
}
//重写Student类的equals()方法,可以通过IDEA快速生成
@Override
public boolean equals(Object o) {
Student s = (Student) o;
return this.name.equals(s.name) && this.age == s.age;
}
案例:ArrayList通过迭代器获取自定义对象指定属性值
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Person("张三", 23));
list.add(new Person("李四", 24));
Iterator it = list.iterator(); //获取迭代器
while(it.hasNext()) {
//System.out.println(it.next().getName() + "..." + it.next().getAge());//next方法只能调用一次,如果调用多次会将指针向后移动多次
Person p = it.next(); //声明对象并将数据存入
System.out.println(p.getName() + "..." + p.getAge()); //打印所需要的属性
}
}
LinkedList的特有功能
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.addFirst("a"); //往头添加元素
list.addFirst("b");
list.addFirst("c");
list.addFirst("d");
list.addLast("e"); //往尾添加元素
//System.out.println(list.getFirst());//获取第一个
//System.out.println(list.getLast());//获取最后一个
//System.out.println(list.removeFirst());//删除第一个
//System.out.println(list.removeLast());//删除最后一个
System.out.println(list.get(1));//获取索引位置的元素,其实并不是靠索引,因为是链表结构,靠的是挨个查询
System.out.println(list);
}
增强for的功能概述和测试(foreach)
-
A:增强for概述
- 简化数组和Collection集合的遍历
-
B:格式:
- for(元素数据类型 变量 : 数组或者Collection集合) {使用变量即可,该变量就是元素}
-
C:案例演示
- 数组,集合存储元素用增强for遍历
D:好处
简化遍历
增强for循环底层依赖的是迭代器(Iterator)
//增强for功能演示
public class CeShi {
public static void main(String[] args) {
ArrayList list1 = new ArrayList<>();
list1.add(new Student("张三", 23));
list1.add(new Student("张三", 23));
list1.add(new Student("李四", 23));
list1.add(new Student("李四", 23));
list1.add(new Student("李四", 23));
for (Student i : list1) {
Student s1 = i;
System.out.println(i.getName());
}
System.out.println("==============================");
int[] arr = {11, 22, 33, 44, 55};
for (int i : arr) {
System.out.println(i);
}
}
}
集合元素的三种删除方式测试
普通for循环,可以删除,但是索引要–
迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常
增强for循环不能删除
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("d");
//1,普通for循环删除,索引要--
/*for(int i = 0; i < list.size(); i++) {
if("b".equals(list.get(i))) {
list.remove(i--); //通过索引删除元素
}
}*/
//2,迭代器删除
/*Iterator it = list.iterator();
while(it.hasNext()) {
if("b".equals(it.next())) {
//list.remove("b"); //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
it.remove();
}
}*/
/*for(Iterator it2 = list.iterator(); it2.hasNext();) {
if("b".equals(it2.next())) {
//list.remove("b"); //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
it2.remove();
}
}*/
//3,增强for循环,增强for循环不能删除,只能遍历
for (String string : list) {
if("b".equals(string)) {
list.remove("b");
}
}
System.out.println(list);
}
单列Set集合:
//Set集合,无索引,不可以重复,无序(存取不一致)
//注意:存储类对象则需要修改类对象的equals和hashCode方法,否则可以存储重复对象
//定义HashSet
HashSet hs = new HashSet<>();
hs.add(new Student("张三", 23));
//定义LinkedHashSet,底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
LinkedHashSet lhs = new LinkedHashSet<>();
lhs.add("a");
//定义TreeSet,用来对象元素进行排序,同样他也可以保证元素的唯一
TreeSet ts = new TreeSet<>();
ts.add(3);
双列Map集合:
Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
A:Map集合的功能概述
a:添加功能
V put(K key,V value):添加元素。
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
b:删除功能
void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回
c:判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
d:获取功能
Set
> entrySet(): V get(Object key):根据键获取值
Set keySet():获取集合中所有键的集合
Collection values():获取集合中所有值的集合
e:长度功能
int size():返回集合中的键值对的个数
Map map = new HashMap<>();
Integer i1 = map.put("张三", 23);//添加
Integer value = map.remove("张三"); //根据键删除元素,返回键对应的值
System.out.println(map.containsKey("张三")); //判断是否包含传入的键
System.out.println(map.containsValue(100)); //判断是否包含传入的值
第一种迭代方式
public static void main(String[] args) {
HashMap map = new HashMap<>();
map.put("张三", 23);
map.put("李四", 24);
map.put("王五", 25);
map.put("赵六", 26);
Integer i = map.get("张三"); //根据键获取值
//获取所有的键
Set keySet = map.keySet(); //获取所有键的集合
Iterator it = keySet.iterator();//获取迭代器
while (it.hasNext()) {
String key = it.next(); //获取每一个键
Integer value = map.get(key);//根据键获取值
System.out.println(key + "=" + value);
}
System.out.println("=======================================");
//使用增强for循环遍历
for (String key : map.keySet()) { //map.keySet()是所有键的集合
System.out.println(key + "=" + map.get(key));
}
}
第二种迭代方式
/**
* Map集合的第二种迭代,根据键值对对象,获取键和值
* A:键值对对象找键和值思路:
* 获取所有键值对对象的集合
* 遍历键值对对象的集合,获取到每一个键值对对象
* 根据键值对对象找键和值
*/
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("张三", 23);
map.put("李四", 24);
map.put("王五", 25);
map.put("赵六", 26);
//Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中
/*Set> entrySet = map.entrySet();
//获取每一个对象
Iterator> it = entrySet.iterator();
while(it.hasNext()) {
//获取每一个Entry对象
Map.Entry en = it.next(); //父类引用指向子类对象
//Entry en = it.next(); //直接获取的是子类对象
String key = en.getKey(); //根据键值对对象获取键
Integer value = en.getValue(); //根据键值对对象获取值
System.out.println(key + "=" + value);
}*/
for(Entry en : map.entrySet()) {
System.out.println(en.getKey() + "=" + en.getValue());
}
}
案例:用HashMap统计字符串中每个字符出现的次数
public class CeShi {
public static void main(String[] args) {
//1,定义一个需要被统计字符的字符串
String s = "abbccddddddcccbbaa";
//2,将字符串转换为字符数组
char[] arr = s.toCharArray();
//3,定义双列集合,存储字符串中字符以及字符出现的次数
HashMap hm = new HashMap<>();
//4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
for (char c : arr) {
//5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,如果集合中包含这个键,就将值加1存储
/*if (!hm.containsKey(c)) {//如果不包含这个键
hm.put(c, 1);
} else {
hm.put(c, hm.get(c) + 1);
} */
hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
}
//6,打印双列集合获取字符出现的次数
for (Character key : hm.keySet()) { //hm.keySet()代表所有键的集合
System.out.println(key + "=" + hm.get(key));//hm.get(key)根据键获取值
}
}
}
集合总结:
Collection(单列集合)
List(存取有序,有索引,可以重复)
ArrayList
底层是数组实现的,线程不安全,查找和修改快,增和删比较慢
LinkedList
底层是链表实现的,线程不安全,增和删比较快,查找和修改比较慢
Vector
底层是数组实现的,线程安全的,无论增删改查都慢
* 如果查找和修改多,用ArrayList
* 如果增和删多,用LinkedList
* 如果都多,用ArrayList
Set(存取无序,无索引,不可以重复)
HashSet
底层是哈希算法实现
LinkedHashSet
底层是链表实现,但是也是可以保证元素唯一,和HashSet原理一样
TreeSet
底层是二叉树算法实现
*一般在开发的时候不需要对存储的元素排序,所以在开发的时候大多用HashSet,HashSet的效率比较高
* TreeSet在面试的时候比较多,问你有几种排序方式,和几种排序方式的区别
Map(双列集合)
HashMap
底层是哈希算法,针对键
LinkedHashMap
底层是链表,针对键
TreeMap
底层是二叉树算法,针对键
*开发中用HashMap比较多