集合

              集合
  1. 集合的概念
    1、 集合是Java API所提供的一系列类,可以用于动态存放多个对象。–集合只能存对象
    2、 集合与数组的不同在于,集合是大小可变的序列,而且元素类型可以不受限定,只要是引用类型
    3、集合类全部支持泛型,是一种数据安全的用法。

  2. 集合框架图
    Java的集合框架从整体上可以分为两大家族。
    1、 Collection(接口)家族。该接口下的所有子孙均存储的是单一对象。
    2、 Map(接口)家族。该接口下的所有子孙均存储的是key-value(键值对)形式的数据。

另外还有三个分支,均是为上述两大家族服务的。
1、 Iterator(迭代器)家族。主要用于遍历Colleciton接口的及其子类而设计。
2、 Comparator(比较器), 在集合中存储对象时候,用于对象之间的比较
Collecitons是工具类。注意该类名带个s,一般就表示工具类。里面提供了N多静态方法,来对Colleciton集合进行操作。
在这里插入图片描述

3.Connection接口
Collection接口-定义了存取对象的方法。有两个非常常用的子接口:
List接口:存放的元素有序且允许有重复的集合接口。
Set接口:存放的元素无序不包含重复的集合接口。

常用方法:
1、 int size(); 返回此collection中的元素数。
2、 boolean isEmpty(); 判断此collection中是否包含元素。
3、 boolean contains(Object obj); 判断此collection是否包含指定的元素。
4、 boolean contains(Collection c); 判断此collection是否包含指定collection中的所有元素。
5、 boolean add(Object element); 向此collection中添加元素。
6、 boolean addAll(Collection c); 将指定collection中的所有元素添加到此collection中
7、 boolean remove(Object element); 从此collection中移除指定的元素。
8、 boolean removeAll(Collection c); 移除此collection中那些也包含在指定collection中的所有元素。
9、 void clear(); 移除些collection中所有的元素。
10、 boolean retainAll(Collection c); 仅保留此collection中那些也包含在指定collection的元素。
11、 Iterator iterator(); 返回在此collection的元素上进行迭代的迭代器。
12、Object[] toArray(); 把此collection转成数组。

4.List接口
List相比Connection新增的几个使用方法;
List接口比Collection接口中新增的几个实用方法:
1、 public Object get(int index) 根据下标,返回列表中的元素
2、 public Object add(int index, Object element);  在列表的指定位置插入指定元素.将当前处于该位置的元素(如果有的话)和所有后续元素向右移动
3、 public Object set(int index, Object element) ; 用指定元素替换列表中指定位置的元素
4、 public Object remove(int index) 移除列表中指定位置的元素
注意:list集合中的元素的索引与数组中元素的索引一样,均是从0开始。

ArrayList集合

  • List接口的实现类:ArrayList、LinkedList
  • 分析ArrayList存储特点:
  • 有序:按什么顺序存进去就按什么顺序取出来
    
  • 存储方式:数组扩容
    
  • 原理:存储第一个元素时,内部给定一个数组,初始为10个空间;当空间不够存时,进行扩容,将原先数组元素拷贝进来;再将新增元素添加到新扩容的空间中
    

在这里插入图片描述

  • LinkedList存储方式:双向链表
  •  原理:当存第一个元素时,创建一个节点,分三个区域,分别为prev,data,next。prev指向上一个节点, 初始为null,data存元素,next存下一个节点初始为null;当创建新节点时,新节点的prev指向上一个节点,上一个节点的 next指向下一个节点;以此类推,构成双向链表。
    

在这里插入图片描述

  • ArrayList VS LinkedList
  • 相同点:存储特点一致,都是List的实现类;都具有有序且允许重复的特点
  • 不同点:存储原理不同
  • 分场景进行效率PK(增删改查):
  •  1.添加:向后追加、指定位置插入
    
  •          向后追加:ArrayList稍高
    
  •          指定位置连续插入:LinkedList高
    
  •  2.删除:指定位置删除:LinkedList高
    
  •  3.查找:就是定位:明显ArrayList块
    
  •  4.修改:定位好,在修改:ArrayLis快
    
  •  结论:ArrayList更常用,常用操作:向后追加和查找
    

5.迭代器iteratior
迭代器应用:
有两个方法:hasNext():判断是否有下一个,next():获取下一个元素

案例:迭代器遍历存自定义对象的集合

泛型:用于约束集合中存储的类型

引入泛型:遍历元素时,要获取本身的类型-强转,如果存储过其他类型的元素,遍历强转时会崩溃;
通过泛型处理:从源头上约束集合存储的类型,存储时不能存其他的类型。

优点:
1.简化集合的使用
2.增强代码的可读性和稳定性

问题:
1.为什么有了基本for和增强for,还需要有迭代器?
----性能上考虑 看本质:增强for就是迭代器

2.迭代器内部用什么方法进行迭代的?
----如果是ArrayList方式存,则用数组方式迭代
----如果是LinkedList方式存,则用链表方式迭代
List list = new ArrayList();
list.add(new Student(“zs”));
list.add(new Student(“ls”));
list.add(new Student(“ww”));
//通过限制存入集合元素类型为Student对象
// list.add(1); 存入其他类型对象强转对象时会报错
Iterator it = list.iterator();
while (it.hasNext()) {
//java.lang.Integer cannot be cast to com.qf.b_iterator.Student
//Student st = (Student)it.next();
System.out.println(it.next().getName());
}

JDK1.4以前不能使用泛型的弊端:
1、 装入集合的数据都会被当作Object对象来存放,从而失去了自己的实际类型。
2、 从集合中取出元素时,需要进行强制类型转换。效率低,容易产生错误。
从JDK1.5开始,sun公司推出了泛型来解决上述问题:
1、在定义一个集合时就指定集合存储的对象的数据类型
如:List list = new ArrayList<>();
2、存入数据时只能存入泛型指定的数据类型,如果存入其他数据类型,则会编译错误。
list.add(1); //编译错误!
3、从集合中取出元素时,无需转型了。
如:Student st = it.next();

6.Set接口
HashSet集合
Set:存储的元素无需且唯一
两个实现类:HashSet,TreeSet
注意:两个类都没有下标操作,所以不能用for循环

HashSet的基本操作、遍历
细节:HashSet的存储–》在内部由HashMap实现的

存储方式:hash算法
原理:当存储第一个元素时,内部给定一张hash表(数组),初始长度16;每个元素都有一个对应的hash值,根据hash值在hash表中可计算出位置,如果该位置为null则直接存储,否则将该元素与该位置的链表元素一一比较;如果找到相同的,则确定唯一性。
在这里插入图片描述
探究唯一性
package com.qf.d_hashset;

import java.util.HashSet;
import java.util.Set;

/**

  • 验证原理:HashSet存自定义对象

  • 目标:确定唯一性—(2个)

  • 实际:打印三个对象–暂时不能确定唯一性–没有重写hashCode和equals

  • 结论:如果想按自己的方式确定唯一性(只要属性值一致认为是唯一的),必须重写hashCode和equals

  • @author Zhouzilong

  • @date 2019年7月30日
    */
    public class Test2 {
    public static void main(String[] args) {
    Set set = new HashSet();
    set.add(new Teacher(“苍老师”));
    set.add(new Teacher(“陈老师”));
    set.add(new Teacher(“苍老师”));
    System.out.println(set);

     Set<String> set2 = new HashSet<String>();
     set2.add("苍老师");
     set2.add("陈老师");
     set2.add("苍老师");
     System.out.println(set2);
    

    }
    }

重写hashCode方法和equals方法之前输出结果:
在这里插入图片描述
重复输出了,没有体现唯一性。因为查看底层实现发现按它的比较算法来说,虽然值是一样,但总体来看是不一样的,所以重复,但我们想要的是值一样就算重复,所以需要重写hashCode方法和equals方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Teacher other = (Teacher) obj;
    if (name == null) {
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    return true;
} 

重写之后:
在这里插入图片描述

TreeSet集合
TreeSet类存储特点:可排序,唯一
*

  • 存储方式:二叉树算法
  • 原理:存储第一个元素时,作为根;存第二个元素时,与根比较 ;如果比根小,
  •       看左子树是否有元素,如果为null,直接存,否则,以左子树为根继续比较;
    
  •       如果比根大,看右子树是否有元素,如果为null,直接存,否则以右子树为
    
  •       根继续比较。
    

在这里插入图片描述
探究唯一性与有序性
package com.qf.e_treeset;

import java.util.Set;
import java.util.TreeSet;

/**

  • 验证原理:
  • TreeSet集合存储自定义对象,看是否能排序和确定唯一。
  • 实验结果:会报错
  • 方案1:
  • 解决方案:存储的对象所在类实现Comparable接口
  • 按自己的方式进行比较和确定唯一
  • 将比较对象转为比较属性
  • 如果是字符串则比较ASCII码
  • @author Zhouzilong
  • @date 2019年7月30日
    */
    public class Test2 {
    public static void main(String[] args) {
    Set set = new TreeSet();
    set.add(new Student(“zs”));
    set.add(new Student(“ls”));
    set.add(new Student(“zs”));
    System.out.println(set);
    }
    }

直接运行,报错com.qf.e_treeset.Student cannot be cast to java.lang.Comparable
Student类无法被转型为Comparable类,说明底层实现中有转型的语句,查询后发现Comparable类为借口,为了能够实现转型,将Student类变为Comparable类的实现类,此时发现需要实现Comparable类的CompareTo方法,先不写方法体。继续看底层实现,发现如下代码
do {
parent = t;
//t为根节点
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);

可以看出,调用compareTo方法用当前对象比较根节点对象,结果小于0放左子树,大于0放右子树,等于0则说明是相等的,直接return。之前重写compareTo方法的方法体正好没写,我们想比对的是值,那么怎么写合适呢?由于要比的值是字符串,当时马上就想到了比较值的字典大小,返回值小于0放左子树( t = t.left;),返回值大于0放右子树(t = t.right;),正好适合这里:
@Override
public int compareTo(Student o) {
return this.name.compareTo(o.name);
}

其中this.name代表调用这个方法的对象的name值,o.name代表对象参数的name值。

另外,用System.out.println(“set”);输出是默认从左子树开始输出,也就是从小到大输出,若调换o.name和this.name的位置,同样是从左子树开始输出,此时自然就为从大到小输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图像识别技术在病虫害检测中的应用是一个快速发展的领域,它结合了计算机视觉和机器学习算法来自动识别和分类植物上的病虫害。以下是这一技术的一些关键步骤和组成部分: 1. **数据收集**:首先需要收集大量的植物图像数据,这些数据包括健康植物的图像以及受不同病虫害影响的植物图像。 2. **图像预处理**:对收集到的图像进行处理,以提高后续分析的准确性。这可能包括调整亮度、对比度、去噪、裁剪、缩放等。 3. **特征提取**:从图像中提取有助于识别病虫害的特征。这些特征可能包括颜色、纹理、形状、边缘等。 4. **模型训练**:使用机器学习算法(如支持向量机、随机森林、卷积神经网络等)来训练模型。训练过程中,算法会学习如何根据提取的特征来识别不同的病虫害。 5. **模型验证和测试**:在独立的测试集上验证模型的性能,以确保其准确性和泛化能力。 6. **部署和应用**:将训练好的模型部署到实际的病虫害检测系统中,可以是移动应用、网页服务或集成到智能农业设备中。 7. **实时监测**:在实际应用中,系统可以实时接收植物图像,并快速给出病虫害的检测结果。 8. **持续学习**:随着时间的推移,系统可以不断学习新的病虫害样本,以提高其识别能力。 9. **用户界面**:为了方便用户使用,通常会有一个用户友好的界面,显示检测结果,并提供进一步的指导或建议。 这项技术的优势在于它可以快速、准确地识别出病虫害,甚至在早期阶段就能发现问题,从而及时采取措施。此外,它还可以减少对化学农药的依赖,支持可持续农业发展。随着技术的不断进步,图像识别在病虫害检测中的应用将越来越广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值