Java 集合---尚硅谷Java入门视频学习
创始人
2024-02-06 06:49:19
  • 问题:什么时候需要一个容纳数据的容器,也就是集合对象?
    Java集合框架中就包含了对不确定个数的数据处理的集合类
  • 问题:如果只是为了容纳数据,可以是直接使用数组,为什么要学习集合?
    数组使用起来不方便。在数据个数不确定的场合,数组使用起来不是很方便

总结:对不确定的有关系的数据进行相同的逻辑处理的场合,使用集合是一个不错的选择

根据数据的不同,Java的集合分为2大体系:

    1. 单一数据体系 : Collection接口定义了相关的规则
      常用的子接口

List :按照插入顺序保存数据,数据可以重复的
具体的实现类: ArrayList, LinkedList
Set : 集,无序保存,数据不能重复
具体的实现类 HashSet
Queue : 队列
具体的实现类:ArrayBlockingQueue

    1. 成对出现的数据体系 : Map接口定义了相关的规则
      所谓的成对的数据,就是2个数据有关系,可以根据第一个数据关联到第二个数据。
      也称之为键值对数据 ,(123123, zhangsan) => (key, value)

具体的实现 : HashMap, Hashtable

1.ArrayList

创建第一个集合对象:ArrayList

 ArrayList list = new ArrayList(3);
  1. 不需要传递构造参数,直接new就可以,底层数组为空数组
  2. 构造参数需要传递一个int类型的值,用于设定底层数组的长度
  3. 构造参数需要传递一个Collection集合类型的值,用于将其他集合中的数据放置在当前集合中
  • 增加数据
    添加数据时,如果集合中没有任何的数据,那么底层会创建长度为10的数组(扩容)
 	// add方法可以增加数据,只要将数据作为参数传递到add方法即可// 添加数据时,如果集合中没有任何的数据,那么底层会创建长度为10的数组list.add("zhangsan");list.add("zhangsan");list.add("wangwu");list.add("zhaoliu");// 获取集合中数据的条数System.out.println(list.size());// 获取指定位置的数据,可以采用索引的方式System.out.println(list.get(1));// 遍历集合中的数据for ( int i = 0; i < list.size(); i++ ) {//System.out.println("集合中的数据:" + list.get(i));}// TODO 如果循环遍历集合数据时,不关心数据的位置,那么可以采用特殊的for循环// for (循环对象:集合) {}for ( Object obj : list ) {System.out.println("集合中的数据:" + obj);}
// add方法可以传递2个参数的,第一个参数表示数据增加的位置(索引),第二个参数表示数据
list.add(1, "zhaoliu");

addAll()方法

		ArrayList list = new ArrayList();list.add("zhangsan");list.add("lisi");list.add("wangwu");list.add("zhangsan");list.add("zhangsan");ArrayList otherList = new ArrayList();otherList.add("1");otherList.add("2");otherList.add("3");list.addAll( otherList );//将otherList 集合追加到list集合末尾
  • 修改数据
    将指定位置的数据进行修改,set方法需要传递2个参数,第一个参数表示数据的位置,第二个参数修改的值。
    方法会返回结果,这个结果就是更新前的值
Object oldVal = list.set(1, "lisi");
System.out.println("修改前的值:" + oldVal);
  • 删除数据
    将指定位置的数据进行删除,remove方法需要传递1个参数,参数表示数据的位置。
    方法会返回结果,这个结果就是删除的值
Object removeVal = list.remove(1);
System.out.println("删除的值:" + removeVal);
// TODO 打印集合对象
System.out.println(list);
  • 其他常用方法
// size方法表示集合内部数据的数量
System.out.println(list.size());
// 清空集合中的数据
list.clear();
// 删除指定集合中的数据
list.removeAll(otherList);  //删除list集合中otherList集合里的数据
// 判断集合中的数据是否为空
System.out.println(list.isEmpty());
// 用于判断集合中是否存在某条数据,返回布尔类型的值
System.out.println(list.contains("zhangsan123"));
// 用于获取数据在索引中的第一个位置,如果数据不存在,那么返回-1
System.out.println(list.indexOf("zhangsan123"));
System.out.println(list.indexOf("zhangsan"));
System.out.println(list.lastIndexOf("zhangsan"));
//集合变数组
Object[] objects = list.toArray();
// 复制新集合
Object clone = list.clone();
ArrayList list1 = (ArrayList)clone;
System.out.println(list);
System.out.println(list1);

2.LinkedList

在这里插入图片描述

  • 构建集合对象
  LinkedList list = new LinkedList();
  • 添加数据
//添加数据
// 增加第一个数据
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
//向指定的位置添加数据 
list.addFirst("lisi"); //增加到数据的前面
list.addLast("2");//增加到数据的后面(默认)
list.add(1, "wangwu"); //添加到第一个位置(0和1之间)
//向集合中添加另一个集合
LinkedList list1 = new LinkedList();
list1.add("zhangsan1");
list1.add("lisi2");
list1.add("wangwu3");
list.addAll(list1);  //将list1集合追加到list集合末尾
  • 获取数据
System.out.println(list.getFirst());
System.out.println(list.getLast());
// 获取数据(遍历数据)
System.out.println(list.get(1));
for ( int i = 0; i < list.size(); i++ ) {System.out.println(list.get(i));
}
for ( Object obj : list ) {System.out.println(obj);
}
  • 修改数据
list.set(1, "zhaoliu");
  • 删除数据
   list.remove("zhangsan");list.removeFirst(); // 删除第一个list.removeLast(); // 删除最后一个list.remove(1);// 删除指定索引
  • 其他方法
System.out.println(list.size());
System.out.println(list.isEmpty());
list.clear();
list.contains("1");
list.element(); // 获取集合第一个数据
list.indexOf("");
list.lastIndexOf("");
list.push("aaa"); // 添加数据到第一个
System.out.println(list.pop()); // 弹出第一个数据

ArrayList和LinkedList对比

在这里插入图片描述

3.泛型

背景

public class Main{public static void main(String[] args) {Person6 person = new Person6();User6 user = new User6();ArrayList list = new ArrayList();list.add(person);list.add(user);list.remove(0);// 从集合中获取的对象类型为ObjectObject o = list.get(0);// 如果想要执行对象的方法,那么需要进行强制类型转换if ( o instanceof  Person6 ) {Person6 p = (Person6)o;p.testPerson();}}
}
class Person6 {public void testPerson() {System.out.println("person...");}
}
class User6 {public void testUser() {System.out.println("user...");}
}

因为多态语法对对象的使用场景进行了约束,从集合中获取的对象类型为Object,不能直接调用对象类型本身的方法,可见集合对象在处理不同类型的数据时比较繁琐。
集合中没有约定存储数据的类型,不同类型的数据都可以存放在里面,保存了不同类型的数据后,处理起来机会比较麻烦。
在这里插入图片描述
在这里插入图片描述

泛型的使用

泛型和类型
在这里插入图片描述
类型相当于一个容器类,可以是集合,也可以是其他类

public class Java07_Collection_Generic {public static void main(String[] args) {// 泛型语法// TODO 泛型和类型的区别// 有时,也把泛型称之为类型参数MyContainer myContainer = new MyContainer();//myContainer.data = new Object();// 类型存在多态的使用方式,但是泛型没有多态的概念test(myContainer);}public static void test(MyContainer myContainer) {System.out.println(myContainer);}
}
// TODO 容器类
class MyContainer {public T data;
}
class User7 {}

4.HashSet

  • 创建对象
 // HashSet : Hash + Set
// Hash : 哈希算法,散列算法
HashSet set = new HashSet();
  • 增加数据
    不会重复存储
// TODo 增加数据
set.add("zhangsan");
set.add("zhangsan");  
set.add("lisi");
set.add("wangwu");  //[zhangsan,lisi,wangwu]

不能修改数据 ,要修改只能先删除再增加。

  • 删除数据
//删除数据
set.remove("wangwu");
  • 查询数据
    数据没有对应的索引,没有查询数据的方法。要查询只能遍历
// TODo 查询数据
for (Object o : set) {System.out.println(o);
}
System.out.println(set);
}
  • 其他常用方法
HashSet set = new HashSet();
ArrayList list = new ArrayList();
list.add("zhangsan");
list.add("lisi");
list.add("wamngwu");
set.addAll(list);
Object[] objects = set.toArray();
System.out.println(set.isEmpty());
set.clear();
set.contains("zhangsan");
System.out.println(set.size());
Object clone = set.clone();
System.out.println(clone);
System.out.println(set);
  • 重复数据的问题
public class Java09_Collection_Set_2 {public static void main(String[] args) {HashSet set = new HashSet();User9 user1 = new User9();user1.id = 1001;user1.name = "zhangsan";System.out.println(user1.hashCode());User9 user2 = new User9();user2.id = 1001;user2.name = "zhangsan";System.out.println(user2.hashCode());User9 user3 = new User9();user3.id = 1002;user3.name = "lisi";set.add(user1);set.add(user2);set.add(user3);System.out.println(set);}
}
class User9 {public int id;public String name;@Overridepublic String toString() {return "User["+id+", "+name+"]";}
}

HashSet中不会有重复的数据,上面的例子中,user1和user2对象虽然属性值相同,但其内存地址不同,在内存中是独立保存的,是两个不同的对象,因此上面的HashSet中存储的是三个对象。

传递给HashSet一个对象时,进行定位操作的方式:传递一个对象时,以对象的hashCode来做哈希运算,找到数据存放的位置。如果这个位置没有存放数据,则直接将数据存储,如果这个位置已经有数据,则通过equals()方法判断两个数据是否相等,如果相等,则直接丢弃即将要存入的数据;如果不相等,则通过链表将两个位置相同的数据连接起来进行存放(HashSet 底层数据结构为 数组 + 链表)。
如果要使HashSet以对象的属性值是否相同为标准,判断存入的两个对象是否相同,则需要将判断对象是否相等以及获取对象hashCode值的方法进行重写。

public class Java09_Collection_Set_2 {public static void main(String[] args) {// TODO 集合 - Collection - Set// HashSet 底层数据结构为 数组 + 链表HashSet set = new HashSet();User9 user1 = new User9();user1.id = 1001;user1.name = "zhangsan";System.out.println(user1.hashCode());User9 user2 = new User9();user2.id = 1001;user2.name = "zhangsan";System.out.println(user2.hashCode());User9 user3 = new User9();user3.id = 1002;user3.name = "lisi";set.add(user1);set.add(user2);set.add(user3);System.out.println(set);}
}
class User9 {public int id;public String name;@Override// 类似于内存地址public int hashCode() {return id;}@Override// 判断两个对象的属性是否完全相同public boolean equals(Object obj) {if ( obj instanceof User9 ) {User9 otherUser = (User9)obj;if ( otherUser.id == this.id ) {if ( otherUser.name.equals(this.name) ) {return true;}}return false;} else {return false;}}@Overridepublic String toString() {return "User["+id+", "+name+"]";}
}

如此,两个对象id值相同时,其hashCode值相同,进行哈希定位时其位置也相同;再根据重写的equals方法,可判断出两个对象属性完全相同,即两个数据为同一个值。因此上面的HashSet中只会存储两个对象。

5.Queue

  • 入队方法
// ArrayBlockingQueue : Array + Blocking(阻塞,堵住) + Queue
ArrayBlockingQueue queue = new ArrayBlockingQueue(3);
// add方法如果增加数据增加不了,直接发生错误。
queue.add("zhangsan");
queue.add("lisi");
queue.add("wangwu");
queue.add("zhaoliu"); // 发生错误,Queue full
queue.put("zhangsan");
System.out.println("第一个人挂号");
queue.put("lisi");
System.out.println("第二个人挂号");
queue.put("wangwu");
System.out.println("第三个人挂号");
queue.put("zhaoliu");  // 不发生错误,但一直阻塞
System.out.println("第四个人挂号");
boolean zhangsan = queue.offer("zhangsan");
System.out.println(zhangsan);   // true
boolean lisi = queue.offer("lisi");
System.out.println(lisi);
boolean wangwu = queue.offer("wangwu");
System.out.println(wangwu);
boolean zhaoliu = queue.offer("zhaoliu");
System.out.println(zhaoliu);  // false
  • 出队方法
System.out.println(queue.poll());  // zhangsan
//当队列中没有数据时,执行此方法会输出null
System.out.println(queue.take());// zhangsan
//当队列中没有数据时,执行此方法会阻塞程序

6. HashMap

在这里插入图片描述
存储原理:根据key,由Hash算法计算存储的位置,可以不能重复,重复则覆盖

// HashMap : Hash + Map
// 数据存储是无序
HashMap map = new HashMap();// 添加数据:put
// 修改数据,put方法也可以修改数据,返回值就是被修改的值
map.put("zhangsan", "1");
System.out.println(map.put("zhangsan", "4"));  //key相同,value会被覆盖   输出覆盖的值 1
map.put("lisi", "2");
map.put("wangwu", "3");
// 修改数据 返回值就是被修改的值   如果不存在则返回null,且不会在map中添加
Object b = map.replace("b", "4"); 
System.out.println(b);//查询数据
System.out.println(map.get("zhangsan"));
// 删除数据
map.remove("zhangsan");
System.out.println(map);
map.remove("zhangsan", "1");  //删除键值对 key value都相同时才删除
// TODO 获取map集合中所有的key
Set set = map.keySet();
for (Object k : set) {System.out.println(map.get(k));  //获取key对应的value
}
System.out.println(map.containsKey("zhangsan"));
Collection values = map.values();
map.containsValue("1");
System.out.println(map);
HashMap map = new HashMap();
// TODO 获取键值对对象
Set> entries = map.entrySet();
for (Map.Entry entry : entries) {System.out.println(entry.getKey() + "=" + entry.getValue()); //lisi=2
}

7.Hashtable

HashMap与Hashtable

  1. 实现方式不一样的 : 继承父类不一样
  2. 底层结构的容量不同: HashMap(16), Hashtable(11)
  3. HashMap的K,V都可以为null, Hashtable的K, V不能是null
  4. HashMap的数据定位采用的是Hash算法,但是Hashtable采用的就是hashcode
  5. HashMap的性能较高,但是Hashtable较低

8.迭代器

HashMap map = new HashMap();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
Set keys = map.keySet();
for (String key : keys) {if ( "b".equals(key) ) {map.remove("b");}System.out.println(map.get(key));
}

在遍历的时候修改会发生错误ConcurrentModificationException

// TODO 迭代器Iterator iterator = keys.iterator();// hasNext方法用于判断是否存在下一条数据while (iterator.hasNext()) {// 获取下一条数据String key = iterator.next();if("b".equals(key)) {// remove方法只能对当前数据删除iterator.remove();}System.out.println(map.get(key));}

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...