Java学习(4):集合

编程入门 行业动态 更新时间:2024-10-12 01:21:59

<a href=https://www.elefans.com/category/jswz/34/1770091.html style=Java学习(4):集合"/>

Java学习(4):集合

目录

  • 一、集合
    • 1. Collection集合的体系特点
    • 2.Collection 集合的常用API
    • 3.Collection 集合的遍历方式
    • 4.Collection集合存储自定义类型的对象
  • 二、 数据结构
    • 1.栈
    • 2.队列
    • 3.数组
    • 4.链表
    • 5.二叉树
    • 6.二叉查找树
    • 7.平衡二叉树
    • 8.红黑树
  • 三、List集合
  • 四、 泛型
  • 五、Set集合
  • 六、可变参数
  • 七、Map集合
  • 八、集合嵌套


一、集合

1.数组 类型确定,长度确定。
2.集合的大小不固定,启动后可以动态变化,类型也可以不固定。

1. Collection集合的体系特点

集合 Collection 单列 、 Map 双列(键值对)

Collection接口是所有集合的根接口。
List系列集合:添加元素是有序、可重复、有索引。
- ArrayList、LinekdList:有序、可重复、有索引。
Set系列结合:
- HashSet:无序、不重复、无索引。
- LinkedHashSet:有序、不重复、无索引。
- TreeSet: 按照大小默认升序排序、不重复、无索引。

//有序 可重复 有索引
ArrayList list = new ArrayList();
list.add("a");
list.add("a");
list.add("e");
list.add("f");System.out.println(list); //[a, a, e, f]System.out.println(list.get(1)); //a//无序 不重复 无索引
HashSet hs = new HashSet();
hs.add("a");
hs.add("a");
hs.add("e");
hs.add("f");
System.out.println(hs); //[a, e, f]

2.Collection 集合的常用API

集合Collection接口中的方法(所有实现类必须拥有的方法)。

//接口多态的方式调用
Collection<String> co = new ArrayList<String>();
//添加元素
co.add("abc");
co.add("bcd");
System.out.println(co);//[abc, bcd]
//清空集合中的元素
co.clear();
System.out.println(co);//[]
if(co.isEmpty()){  //是否为空System.out.println("empty");
}
//添加元素
co.add("abc");
co.add("bcd");
if(co.contains("bcd")){ //判断是否存在co.remove("bcd");  //删除指定数据
}
System.out.println(co);//[abc]
System.out.println(co.size()); //1 集合长度
Object[] objects = co.toArray();//转成数组Collection<String> c1 = new ArrayList<>();
c1.add("java1");
c1.add("java2");
Collection<String> c2 = new ArrayList<>();
c2.add("赵敏");
c2.add("殷素素");
// addAll把c2集合的元素全部倒入到c1中去。
c1.addAll(c2);

泛型用来约束指定类型的数据,必须使用引用类型包装类。

3.Collection 集合的遍历方式

  1. Iterator接口 迭代器
    Java中提供了许多集合,他们在存储时方式不同。取出时通过一种通用的方式。如果有就取出。
    接口Iterator :两个抽象方法
    boolean hasNext() 判断集合中还有没有可以被取出的元素,如果有返回true。
    next() 取出集合中的下一个元素
    使用ArrayList集合的对象
    Iterator it = array.iterator(); 运行结果就是Iterator接口的实现类对象
    It是接口的实现类对象,调用方法hasNext和next集合元素迭代
Collection<String> co = new ArrayList<String>();
co.add("abc");
co.add("bcd");
co.add("abc");
Iterator<String> it = co.iterator();
while(it.hasNext()){System.out.println(it.next());
}//for写法
for(Iterator<String> it = co.iterator();it.hasNext();){System.out.println(it.next());
}//使用迭代器遍历集合时改变集合会报错。
Iterator<String> it = co.iterator();
while(it.hasNext()){String val = it.next();if(val=="abc")Co.add("aa"); //迭代器工作时 不可以改变集合System.out.println(val);
}
  1. 增强for循环

好处:代码少,方便遍历
弊端:没有索引,不能操作容器里面的元素

for(数据类型 变量名 : 数组或集合){System.out.println(变量名);
}ArrayList<String> djdj = new ArrayList<>();
djdj.add("a");for(String s : djdj){//djdj.remove("java"); //报错 不可以这样做System.out.println(s);
}djdj.for回车 idea自动补全
  1. lambda表达式遍历集合
ArrayList<String> djdj = new ArrayList<>();
djdj.add("a");djdj.forEach(s->{//djdj.remove("a"); //报错System.out.println(s);
});for(int i = 0;i<djdj.size();i++){djdj.remove("a"); //这种可以删 但是会漏删数据
}for(int i = djdj.size() - 1;i>=0;i--){djdj.remove("a") //从后面往前删
}

4.Collection集合存储自定义类型的对象

Student student = new Student();
student.name = "aa";
student.age=21;
ArrayList<Student> students = new ArrayList<>();students.forEach(s->{System.out.println(s.name);
});

二、 数据结构

数据结构是计算机底层存储、组织数据的方式,是指数据相互之间是以什么方式排列在一起的。

1.栈

先进后出,类似子弹夹,最先进入的最后出 最后进入的最先出。

2.队列

先进先出,类似排队做核酸,先做完的先走,后做完的后走。

3.数组

内存中的一块连续区域,查询速度快,通过索引快速找到指定值,但是删除效率低,所有元素向迁移。添加效率低,在指定位置添加后 所有元素后移。

4.链表

链表中的元素在内存中是不连续的,每个元素节点包含数据值和下一个元素的地址。
链表查询慢,无论查询哪个数据都要从头开始找。
但是增删相对快 在ac之间增加一个数据b 1,将数据a对应的下一个数据指向b,2.将数据b的下一个地址指向数据c。

5.二叉树

只能有一个根节点,每个节点最多支持2个直接子节点。

6.二叉查找树

提高检索数据的性能

每一个节点上最多两个节点,
左子树上所有的节点值都小于根节点
右子树上所有的节点值都大于根节点
在查找数据的时候 如果大于根节点就直接去右子树上查找,所以查找效率高。

7.平衡二叉树


二叉查找树存放时,如果数据都是大于根节点的,那么数据一直往右子树上插,所以会有瘸子现象,查询速度就会变慢。因此出现了平衡二叉树。将根节点变为11,左旋一下。

任意节点的左右两个子树的高度差不超过1,添加数据的时候会自动左旋右旋,保证二叉树的平衡。

8.红黑树

每一个节点可以是红或者黑,红黑树不是通过高度平衡的,而是通过颜色。
根节点必须是黑色的,子节点是黑红交替的。
如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的。

三、List集合

有序的collection,可以对每个元素的插入位置进行精确的控制,根据整数索引控制。

  • 实现类:ArrayList、LinekdList:有序,可重复,有索引。
  • ArrayList底层是基于数组实现的,查询元素快,增删相对慢。
  • LinkedList底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的。

对一个集合的操作如果大多是首尾操作那么推荐使用LinkedList类。

LinkedList<Integer> link = new LinkedList<Integer>();
link.add(1);
link.addLast(2);//添加到当前末尾
link.add(3);
link.addFirst(4); //添加到当前开头
if(!link.isEmpty()){ //link.size() != 0System.out.println(link); //[4, 1, 2, 3]System.out.println(link.getFirst()); //获取开头System.out.println(link.getLast()); //获取结尾
}
link.removeFirst();
link.removeLast();
System.out.println(link);//[1, 2]

四、 泛型

使用集合时,明确集合中的元素类型。不会像arrayList那样object强转异常。
Java泛型是伪泛型
ArrayList 编译手段
arr.add(“”) 不是String的时候编译失败
但是编译后的class文件,是没有泛型的

修饰符 class 类名<代表泛型的变量> { }

//例如,API中的ArrayList集合:
class ArrayList<E>{public boolean add(E e){ }public E get(int index){  }
}//创建对象时,确定泛型的类型
ArrayList<String> list = new ArrayList<String>();
//此时,变量E的值就是String类型
class ArrayList<String>{public boolean add(String e){ }public String get(int index){  }
}
ArrayList<Integer> list = new ArrayList<Integer>();
//此时,变量E的值就是Integer类型
class ArrayList<Integer>{public boolean add(Integer e){ }public Integer get(int index){  }
}

?泛型的通配符

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;public class Main {public static void main(String[] args){ArrayList<Integer> nums = new ArrayList<Integer>();nums.add(1);nums.add(2);ArrayList<String> strs = new ArrayList<String>();strs.add("abc");strs.add("def");iterator(nums);iterator(strs);}public static void iterator(Collection<?> coll){Iterator<?> it = coll.iterator();while(it.hasNext()){System.out.println(it.next());}}
}

泛型的限定

//创建3个集合对象
ArrayList<ChuShi> cs = new ArrayList<ChuShi>();
ArrayList<FuWuYuan> fwy = new ArrayList<FuWuYuan>();
ArrayList<JingLi> jl = new ArrayList<JingLi>();
//每个集合存储自己的元素
cs.add(new ChuShi("张三", "后厨001"));
cs.add(new ChuShi("李四", "后厨002"));
fwy.add(new FuWuYuan("翠花", "服务部001"));
fwy.add(new FuWuYuan("酸菜", "服务部002"));
jl.add(new JingLi("小名", "董事会001", 123456789.32));
jl.add(new JingLi("小强", "董事会002", 123456789.33));
iterator(jl);
iterator(fwy);
iterator(cs);// ? extends Car 上限 必须是Car子类
// ? super Car 下限 必须是Car父类
//方法参数: 控制,可以传递Employee对象,也可以传递Employee的子类的对象
public static void iterator(ArrayList<? extends Employee> array){Iterator<? extends Employee> it = array.iterator();while(it.hasNext()){//获取出的next() 数据类型,是什么EmployeeEmployee e = it.next();e.work();}
}

//泛型类
public class PageOf<T> {private Integer page;private Integer rowsCount;private Integer totalCount;private Integer totalPages;private List<T> data;
}//使用
PageOf<MyGoodsDto> pageData = new PageOf<>();
pageData.setData(list);
pageData.setTotalPages(offsetPage.getPages());
pageData.setTotalCount((int) offsetPage.getTotal());
pageData.setRowsCount(offsetPage.getPageSize());
pageData.setPage(param.getPage());
return pageData;
//泛型接口public interface Mapper<T>{
}public interface AccountDao extends Mapper<Account> {}//泛型接口可以约束实现类,实现类可以在实现接口的时候传入自己操作的数据类型.
//就可以使用该接口里面的方法,重写或者直接调用。

五、Set集合

无序:存取顺序不一致,一次。
不重复:可以去除重复数据。
无索引:没有带索引的方法,不能使用for循环遍历。

实现类:

  1. HashSet:无序、不重复、无索引。
  2. LinkedHashSet:有序,不重复,无索引。
  3. TreeSet:排序、不重复、无索引。
HashSet<String> set = new HashSet<String>();
set.add("haha1");
set.add("haha1");//如果存入重复的,只存进去一个。
set.add("def3");
set.add("ghi4");for(String s : set){System.out.println(s); //def3 haha1 ghi4 执行几次都是这个顺序
}

HashSet集合底层采取哈希表存储的数据。
哈希表是一种对增删改查数据性能较好的结构。

哈希表的组成 1.8之前 数组+链表组成
1.8之后 底层采用 数组+链表+红黑树 组成

哈希值
是JDK根据对象的地址,按照某种规则算出来的int类型的数值。
Object API : public int hashCode() 返回对象的哈希值。
同一个对象调用hashCode()方法多次返回的哈希值是相同的。

LinkedHashSet
这里的有序指的是保证存储和读取的元素顺序一致。
底层原理,依然是哈希表,但是每个元素又额外多了一个双链表的机制记录存储的顺序。

Set<String> sets = new LinkedHashSet<>(); // 有序  不重复 无索引
sets.add("MySQL");
sets.add("MySQL");
sets.add("Java");
sets.add("Java");
sets.add("HTML");
sets.add("HTML");
sets.add("SpringBoot");
sets.add("SpringBoot");
System.out.println(sets);

TreeSet
可排序:按照元素的大小默认升序排序。
底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
如果存储的是对象则需要给一个排序规则。

Set<Apple> apples = new TreeSet<>(( o1,  o2) ->  Doublepare(o2.getPrice() , o1.getPrice())  );
apples.add(new Apple("红富士", "红色", 9.9, 500));
apples.add(new Apple("青苹果", "绿色", 15.9, 300));
apples.add(new Apple("绿苹果", "青色", 29.9, 400));
apples.add(new Apple("黄苹果", "黄色", 9.8, 500));
System.out.println(apples);

Collections.addAll 像集合添加一批数据。
Collections.shuffle 打乱顺序
Collections.sort 排序

List<String> names = new ArrayList<>();
//names.add("楚留香");
//names.add("胡铁花");
//names.add("张无忌");
//names.add("陆小凤");
Collections.addAll(names, "楚留香","胡铁花", "张无忌","陆小凤");
System.out.println(names);// 2、public static void shuffle(List<?> list) :打乱集合顺序。
Collections.shuffle(names);
System.out.println(names);// 3、 public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。 (排值特性的元素)
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 12, 23, 2, 4);
System.out.println(list);
Collections.sort(list);
System.out.println(list);

六、可变参数

前提:方法参数的数据类型需要确定,参数的个数不确定。

public static void main(String[] args) {sum(); // 1、不传参数sum(10); // 2、可以传输一个参数sum(10, 20, 30); // 3、可以传输多个参数sum(new int[]{10, 20, 30, 40, 50}); // 4、可以传输一个数组}/**注意:一个形参列表中只能有一个可变参数,可变参数必须放在形参列表的最后面* @param nums*/public static void sum(  int...nums){// 注意:可变参数在方法内部其实就是一个数组。 numsSystem.out.println("元素个数:" + nums.length);System.out.println("元素内容:" + Arrays.toString(nums));}

一个形参列表只能有一个可变参数。
可变参数必须放在形参列表的最后面。

七、Map集合

键值对集合,不能重复key,常用集合为HashMap集合、LinkedHashMap集合。

Map集合是一种双列集合,每个元素都有两个数据
每个元素的格式 key=value。也被称为键值对集合。


HashMap:元素无序,不重复,无索引。
LinkedHashMap:有序,不重复,无索引。
TreeMap:排序,不重复,无索引。

LinkedHashMap

Map<String, Integer> maps = new LinkedHashMap<>();
maps.put("鸿星尔克", 3);
maps.put("Java", 1);
maps.put("枸杞", 100);
maps.put("Java", 100); // 覆盖前面的数据
maps.put(null, null);
System.out.println(maps); //有序

HashMap

HashMap<Integer,String> map = new HashMap<Integer,String>();
//添加键值对
map.put(1,"a");
map.put(2,"b");
map.put(1,"c"); //key重复 会覆盖原有value
System.out.println(map);//{1=c, 2=b}String val = map.get(1); //get通过key获取value
System.out.println(val); //cmap.remove(1); //移除map.containKey(1); //是否存在key
map.containValue("c"); //是否存在值 // 判断集合是否为空,为空返回true ,反之!
System.out.println(maps.isEmpty());//返回set keySet()返回所有key
Set<Integer> keys = map.keySet();for(int i : keys){System.out.println(i+":" +map.get(i));
}

Entry 键值对对象
Entry将键值对的对应关系封装成了对象,在遍历map集合时,就可以从每一个键值对Entry对象中获取对应的key与value。

//返回set entrySet()返回所有entry对象
Set<Map.Entry<Integer, String>> entrys = map.entrySet();for (Map.Entry<Integer, String> entry : entrys) {System.out.println(entry.getKey() + ":" + entry.getValue());
}

HashTable 线程安全集合,运行速度比较慢 不允许存null key,null value
HashMap 线程不安全集合,运行速度快 可以存null key,null value

存储对象

 // Map集合是根据键去除重复元素
Map<Student, String> maps = new HashMap<>();Student s1 = new Student("无恙", 20, '男');
Student s2 = new Student("无恙", 20, '男');
Student s3 = new Student("周雄", 21, '男');maps.put(s1, "北京");
maps.put(s2, "上海");
maps.put(s3, "广州");System.out.println(maps);

TreeMap 存对象时给个排序规则

Map<Integer, String> maps1 = new TreeMap<>();
maps1.put(13 , "王麻子");
maps1.put(1 , "张三");
maps1.put(3 , "县长");
System.out.println(maps1);// TreeMap集合自带排序。  可排序 不重复(只要大小规则一样就认为重复)  无索引
Map<Apple, String> maps2 = new TreeMap<>((Apple o1,Apple o2)-> {return Doublepare(o2.getPrice() , o1.getPrice()); // 按照价格降序排序!
});
maps2.put(new Apple("红富士", "红色", 9.9, 500), "山东" );
maps2.put(new Apple("青苹果", "绿色", 15.9, 300), "广州");
maps2.put(new Apple("绿苹果", "青色", 29.9, 400), "江西");
maps2.put(new Apple("黄苹果", "黄色", 9.8, 500), "湖北");

八、集合嵌套

// 1、要求程序记录每个学生选择的情况。
// 使用一个Map集合存储。
Map<String, List<String>> data = new HashMap<>();// 2、把学生选择的数据存入进去。
List<String> selects = new ArrayList<>();
Collections.addAll(selects, "A", "C");
data.put("罗勇", selects);List<String> selects1 = new ArrayList<>();
Collections.addAll(selects1, "B", "C" , "D");
data.put("胡涛", selects1);List<String> selects2 = new ArrayList<>();
Collections.addAll(selects2 , "A",  "B", "C" , "D");
data.put("刘军", selects2);System.out.println(data);// 3、统计每个景点选择的人数。
Map<String, Integer> infos = new HashMap<>(); // {}// 4、提取所有人选择的景点的信息。
Collection<List<String>> values = data.values();
System.out.println(values);
// values = [[A, B, C, D], [B, C, D], [A, C]]
//             valuefor (List<String> value : values) {for (String s : value) {// 有没有包含这个景点if(infos.containsKey(s)){infos.put(s, infos.get(s) + 1);}else {infos.put(s , 1);}}
}System.out.println(infos);

不可变集合

// 1、不可变的List集合
List<String> strings = Arrays.asList("sdf", "sdf");List<Double> lists = List.of(569.5, 700.5, 523.0,  570.5);
// lists.add(689.0);
// lists.set(2, 698.5);
// System.out.println(lists);
double score = lists.get(1);
System.out.println(score);// 2、不可变的Set集合
Set<String> names = Set.of("迪丽热巴", "迪丽热九", "马尔扎哈", "卡尔眨巴" );
// names.add("三少爷");
System.out.println(names);// 3、不可变的Map集合
Map<String, Integer> maps = Map.of("huawei",2, "Java开发", 1 , "手表", 1);
// maps.put("衣服", 3);
System.out.println(maps);

更多推荐

Java学习(4):集合

本文发布于:2024-03-09 19:34:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1725923.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!