IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 22-04-26 西安 javaSE(16) Collection、List、Set集合 -> 正文阅读

[游戏开发]22-04-26 西安 javaSE(16) Collection、List、Set集合

集合:用于存储、获取、操作对象的容器
数组的不好处:数组的长度不可变

集合的特点:
1、集合的长度是可变的
2、集合中可以存储是任意类型的对象且只能存储对象


Collection接口:java.util.Collection
? ? ? ? ?Collection 接口是 List、Set 和 Queue 接口的父接口
Collection接口中的方法:

boolean add(E e) ;//向集合中添加元素
int size() ?;//获取集合中有效元素个数
void clear() ?;//清空集合
isEmpty();//判断集合是否为空
addAll(Collection coll);//将coll所有元素们一个一个加进去
contains();//判断集合中是否某个元素是否存在,依据是equals
containsAll();?跟顺序有关吗,无关//
remove();//要删除先判断有没有,contains
removeAll();//删除的是俩个集合的交集
retainAll();//取得是俩个集合的交集
toArray();将集合转数组
    @Test
    public void testA() {
        //将数组转集合
        Collection c1 = Arrays.asList(1, 2, 3, 4, 5, 6);
        Collection c2 = Arrays.asList(6, 3, 1);
        //如果此 c1 包含指定 c2 中的所有元素,则返回 true。
        System.out.println(c1.containsAll(c2));
    }

List接口:
有序[因为list集合具有索引值]? ?/? ?且可重复的。有序的意思是存进去的顺序和取出来的顺序是一样的。
List接口在Collection接口上增加了一些根据元素索引来操作集合的特有方法

Arrays.asList(…) 方法返回的 List 集合既不是 ArrayList 实例,也不是 Vector 实例而是Arrays的内部类ArrayList

void add(int index, Object ele)
boolean addAll(int index, Collection eles)
Object get(int index);获取指定
int indexOf(Object obj)//从前往后找指定元素的索引值,找不到返回-1
int lastIndexOf(Object obj);//从后往前找
Object remove(int index);//按照指定索引删除。和Collection接口的按照元素删构成重载,删除指定位置元素  返回被删除元素
Object set(int index, Object ele);//替换指定索引元素,返回替换前的元素
List subList(int fromIndex, int toIndex)//截取子集合,左闭右开

List接口的实现类ArrayList:
ArrayList:底层就是很好的封装了数组,采用数组结构存储,适用于查询多的
1.利用ArrayList()默认数组长度

  • jdk1.7,数组长度10;
  • jdk1.8,数组长度0【默认{}】,做任何小操作则数组长度变为10。

ArrayList(int initialCapacity) 也可以通过有参构造器指定数组长度。
2.扩容
以原来容量的1.5倍来扩容。

List接口的实现类LinkedList??:

LinkedList是一个双向链表。前向索引first和后向索引 last。适用于增删操作
LinkedList提供了大量首尾操作的方法

LinkedList特有的方法:
void addFirst(Object obj)
void addLast(Object obj)	
Object getFirst()
Object getLast()
Object removeFirst();//移除并返回集合中第一个元素,如果集合为空报异常
Object removeLast();//移除并返回集合中最后一个元素,如果集合为空报异常


在开发时,LinkedList集合也可以作为堆栈,队列的结构使用

public class SylQueue {
    //底层使用LinkedList封装Queue
    LinkedList ll=new LinkedList();

    public SylQueue() {

    }
    //添加
    public void add(Object obj){
        ll.addFirst(obj);
    }

    //获取
    public Object get(){
//        return ll.removeFirst();//达成后进先出的堆栈效果
        return ll.removeLast();//达成后进后出的队列效果

    }

    //判断
    public boolean isNull(){
        return ll.isEmpty();
    }

    public String getAll(){
        return ll.toString();
    }

}
public class ExceptionTest {
    @Test
    public void testA() {
        SylQueue sylQueue = new SylQueue();
        sylQueue.add("a");
        sylQueue.add("b");
        sylQueue.add("c");
        sylQueue.add("d");
        sylQueue.add("e");
        String all = sylQueue.getAll();
        System.out.println(all);
        System.out.println("=================");
        Object o = sylQueue.get();
        String all2 = sylQueue.getAll();
        System.out.println(all2);
        System.out.println("=================");

    }
}

问题3:
LinkedList中get(index i)和数组有啥区别【源码】
index i <.size(),从前往后找,反之从后往前找。


java.util.Set:无序不可重复的。

set集合里的元素是无序不可重复的,且set集合没有下标这个说法。

Set接口实现类:
HashSet:是一个set接口的典型实现类【jdk1.7 底层:数组+链表】

? ?LinkedHashSet

TreeSet


HashSet 具有以下特点:

  1. 不能保证元素的排列顺序
  2. HashSet 不是线程安全的
  3. 集合元素可以是 null

一个有意思关于set集合元素不可以重复的Demo

生成一个Person类,嗯。。完全生成的,没有技术含量

public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) && Objects.equals(age, person.age);
    }

//    @Override
//    public int hashCode() {
//        return Objects.hash(name, age);
//    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class ExceptionTest {
    @Test
    public void testA() {
        Set set = new HashSet();
        set.add(new String("苹果"));
        set.add(new String("苹果"));
        set.add(new Person("zhangsan",18));
        set.add(new Person("zhangsan",18));
        System.out.println(set);
    }
}

当Person类没有重写hashCode方法的时候,上面代码输出

?Person类重写了hashCode()之后,输出结果如下:

总结:
1、HashSet为什么不用equals?
? ? ?要是用了则会每次给set集合添加值都会和每一个元素都比较一次,都累死了。

2、调用Object类的hashCode()任何对象都产生一个唯一的哈希码值

3、哈希算法:会将哈希码值变为数组的索引值,hash算法是一种可以从任何数据中提取出其“指纹”的数据摘要算法,它将任意大小的数据映射到一个固定大小的序列上,这个序列被称为hash code。

总的原则:在给set集合存储的时候,俩个对象哈希值是一样的,那他俩一定是一样的

1、那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。
如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式

2.重写的目的:让内容一样的对象不能存到set集合里。
3.重写的规则:当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等。

3.重写hashCode方法是都调这个工具类吗??
?Objects.hash(name, price);

HashSet集合存储过程:

1.先调用存储对象的hashcode()方法,补重写的话会调用Object中hashcode(),让每一个对象都对应唯一的,此时连equals机会都没。

//Person类不重写HashCode方法的话,调用Object类中的,则下面俩个 Person对象
//即使内容一样,我们不想让它重复存储到set集合,是做不到的。因为不重写会生成俩个哈希码值       
set.add(new Person("zhangsan",18));
set.add(new Person("zhangsan",18));

2.重写哈希方法的目的:属性相同,生成的哈希值也相同,同时equals返回true。
3.从哈希码值经过哈希运算到数组之后比较equals()方法,不再使用哈希码值比较了

了解一下!!在调用Object类的toString()时,

打印的字符串:getClass().getName() + '@' + Integer.toHexString(hashCode())//对象哈希码的无符号十六进制

-------------------------------

4、HashSet底层是一个数组,默认长度16。
加载因子:0.75,

扩容原则:【以原来的2倍】


jdk1.8? HashSet又多了一个:数组+链表+红黑树。

红黑树是解决二叉树的平衡问题的。

当链表的长度达到了>=8-1;i并且集合中总元素的个数超过了64,这个链表就会转为红黑树。要不然链表上每一个元素都要和新加的元素equals。有了红黑树就可以顺着hashcode值比较,往下溜。


LinkedHashSet 继承 HashSet
是链表和哈希表组合的一个数据存储结构,相比于HashSet 多了一个链表维护集合中的元素,效率变低了。
LinkedHashSet遍历的时候直接一根列表,可以按添加顺序遍历,且遍历时不用过滤null值。

public class Demo {
    public static void main(String[] args) {
        LinkedHashSet set = new LinkedHashSet();
        set.add(10);
        set.add(8);
        set.add(1);
        set.add(11);
        //LinkedHashSet会按照添加顺序遍历
        System.out.println(set);
    }
}


java.util.TreeSet
底层采用红黑树,有自己指定的排序方式。
2.compareTo,返回正数,0,负数
3.要是不是Person类怎么返回呢,应该是抛出异常吧。在TreeSet中应用的时候返回0可以。
如果返回0,在TreeSet中会视为重复,是对的。
4。为啥compareTo方法形参不不直接写Person 【方法重写】


Collection接口集合实现类的遍历
1.使用增强for循环 【java5提供】

for(元素数据类型 变量名:被遍历的集合){
}
注意:增强for循环不擅长改变数组中的值。

代码案例如下:

?增强for循环 也可以遍历数组【但是要改变数组中某一个值,改不了】

    @Test
    public void test6() {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(1);

        System.out.println(arrayList);//[1,2,1]
        for (Integer i : arrayList) {
            System.out.println("i="+i);
            if(i==2){
               i=1;
            }
        }
        System.out.println(arrayList);//[1,2,1]
    }
}

结果:

那正确的操作方式呢?

发现,set方法是根据索引去修改值得,在增强for循环里没有索引值,自然也就不能改值了

    @Test
    public void test6() {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(1);

        System.out.println(arrayList);//[1,2,1]
        for (int i = 0; i < arrayList.size(); i++) {
            if(arrayList.get(i)==2){
                //public E set(int index, E element)
                arrayList.set(i,1);
            }
        }
        System.out.println(arrayList);//[1,2,1]
    }


Collection集合遍历的第二种方式:迭代器

迭代器Iterator

Collection中有一个方法:Iterator ?iterator() ;//返回Iterator的实例,交给迭代器遍历

首先看看迭代器对象的3个方法,真老六啊

  • hasNext() ?如果仍有元素可以迭代,返回true
  • next() ?返回迭代的下一个元素
  • remove() 移除元素

使用迭代器遍历集合是固定写法,如下遍历一个TreeSet

    @Test
    public void testIter(){
        TreeSet set = new TreeSet();
        set.add(10);
        set.add(8);
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);
        }
      //  System.out.println(iterator.next()); 当next()没有值时,NoSuchElementException
    }

?

迭代器Iterator进行list集合元素的删除?

在集合结构发生变化时,迭代器必须重新获取,不然当你下一次调next()方法时,会报异常。

俩个remove方法

下图最重要的就是,你在while循环里调用集合自带的remove方法删除元素是不可取的,想在迭代时删除,可以,但你必须用我迭代器自己的remove方法。

ListIterator【列表迭代器】

是List集合特有的迭代器,会多一些方法

1.previous()?//获取前一个元素

2.hasPrevious()//获取前一个元素


map集合的所有操作,可以去看同样的那一篇

2021/11/07 北京 List集合,map集合,Collection集合,set集合_£小羽毛的博客-CSDN博客

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-29 12:26:54  更:2022-04-29 12:29:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 8:55:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码