JavaBean
- Java中专门用于封装数据的类
- 开发规范:
- 属性使用private修饰
- 提供public的get/set方法
- 提供无参构造器、带参构造器
- 重写toString()
- 重写hashCode和equals方法
- 实现Serializable接口
业务逻辑
- 在具体项目中实现某一个功能的逻辑
- 业务逻辑会因项目而模块而有很大的差异
- 在课程中仅会涉及到一些特别普遍的业务逻辑
- 举例:
- 功能:基于合同中录入的工资,计算本月该给这个员工发多少钱,并生成工资条信息
- 业务逻辑:
- 应发工资:基本工资+绩效工资+奖金+补助
- 代扣工资:五险一金代扣、个税代扣
- 五险一金代扣:基本工资*代扣比例
- 个税代扣=应纳税所得额(应发工资-五险一金代扣)*适用的税率
- 实发工资=应发工资-代扣工资
- 课程中涉及:
- 电商类常用的业务
- 基本的数据分析的业务
- 项目峰会
集合(Collection)
1. 概念
- 集合 — 用于存储批量数据的对象。可以将它看作是一个可变长度的数组。
- java.util包中提供了一系列可以使用的集合类,称为集合框架。
- 集合框架API主要包含以下接口:
- Collection:表示不按添加顺序存放对象的集合,集合内元素可以重复,即“无序可重复”集合
- Set:“无序不可重复”集合
- List:“有序可重复”集合
- 注意:
- 有序/无序:是否保证按照元素的添加顺序去存放元素
- 可重复和不可重复:是通过equals等方法去判断的
2. 集合API
对比:
- set是无序不可重复的,没有提供基于index去操作集合中元素的方法
- list是有序可重复的,提供了基于index去操作集合中元素的方法
- add(int index, Object obj)
- remove(int index)
- set(int index, Object obj)
- get(int index)
- for-each遍历 或 普通for循环遍历
3. 集合的遍历
- 集合的主要用途是保存批量对象。
- 集合的主要被访问方式是由程序遍历访问集合中保存的对象
- 可以使用增强型for循环遍历访问集合中的对象。
public class TestCollection {
public static void main(String[] args) {
Set set = new HashSet();
set.add(new Integer(123));
System.out.println("添加Integer125:" + set.add(125));
System.out.println("添加Integer125:" + set.add(125));
set.add("abcdf");
set.add(new String("abcdfghi"));
set.add(new Student());
//已完成Set集合的存储
System.out.println("Set集合是否为空:" + set.isEmpty());
System.out.println("Set集合是否包含123:" + set.contains(123));
System.out.println("Set集合中的元素个数:" + set.size());
System.out.println(set);
for (Object o: set) {
System.out.println("Set集合中的元素:" + o);
}
System.out.println("-----------------------------------");
List list = new ArrayList();
list.add(new Integer(123));
System.out.println("添加Integer125:" + list.add(125));
System.out.println("添加Integer125:" + list.add(125));
list.add("abcdf");
list.add(new String("abcdfghi"));
list.add(new Student());
//已完成List集合的存储
System.out.println("获取第5个元素:" + list.get(4));
System.out.println("检索元素abcdf位置:" + list.indexOf("abcdf"));
System.out.println("检索元素120的位置:" + list.indexOf(120));
System.out.println("List集合中的元素个数:" + list.size());
System.out.println(list);
for (Object o: list) {
System.out.println("List集合中的元素:" + o);
}
}
}
4. 泛型(<>)
-
集合类中的元素使用Object类型,以允许不同的添加和获取类型。当获取集合中所需对象时,必须进行强制类型转型。
-
例如:
List list = new ArrayList();
list.add(“Hello world”);
list.add(123);
String str1 = (String)list.get(0);
String str2 = (String)list.get(1); //产生异常
-
泛型机制可以限定集合中保存的数据的类型,在使用了泛型的集合中,获取到的数据会被自动转变成泛型指定的类型
-
泛型机制为编写代码提供了便利,同时提供了编译时的类型安全检查。
-
泛型支持多态
-
使用集合编程时,应结合使用泛型。例如:
ArrayList<String> list = new ArrayList<String>();
list.add(“Hello world”);
String str = list.get(0);
-
泛型以< >形式呈现, < >中的类型约束了集合所能存储的对象类型。这样在获取集合中对象时,不必再进行强制类型转型。
-
< >中的类称为泛型的类型参数。
public class TestGeneric {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
//set.add(new Integer(123)); 非法类型,以下同
//System.out.println("添加Integer125:" + set.add(125));
//System.out.println("添加Integer125:" + set.add(125));
set.add(new String("public"));
set.add("class");
set.add("abcdf");
set.add(new String("abcdfghi"));
//set.add(new Student());
System.out.println("Set集合中的元素个数:" + set.size());
System.out.println(set);
for (String s: set) {
System.out.println("Set集合中的元素:" + s);
System.out.println(s.toUpperCase());
}
System.out.println("----------------------");
List<String> list = new LinkedList<String>();
//list.add(new Integer(123));
//System.out.println("添加Integer125:" + list.add(125));
//System.out.println("添加Integer125:" + list.add(125));
list.add("abcdf");
list.add(new String("abcdfghi"));
list.add(new String("public"));
System.out.println("List集合中的元素个数:" + list.size());
System.out.println(list);
for (String s : list) {
System.out.println("List集合中的元素:" + s);
System.out.println(s.toUpperCase());
}
}
}
集合应用
集合算法与数据结构
-
无论是Set集合,还是List集合,均提供了多个实现类
-
这些类对于在存放对象数据时,其内部的数据组织形式是完全不同的
-
数据组织的形式,称为数据结构。不同的数据结构,需要通过不同的算法来支持对其访问
public class TestSetData {
public static void main(String[] args) {
Set<String> hashSet = new HashSet<String>();
hashSet.add("36");
hashSet.add("20");
hashSet.add("57");
hashSet.add("26");
hashSet.add("78");
hashSet.add("16");
System.out.println("HashSet=" + hashSet);
System.out.println("--------------------------------");
Set<String> treeSet = new TreeSet<String>();
treeSet.add("36");
treeSet.add("20");
treeSet.add("57");
treeSet.add("26");
treeSet.add("78");
treeSet.add("16");
System.out.println("TreeSet=" + treeSet);
}
}
List集合数据结构
- 常用的List集合实现类包括:
- ArrayList:以数组数据结构来存放和管理数据
- LinkedList:以双向链表数据结构来存放和管理数据
public class TestListData {
public static void main(String[] args) {
List<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(345);
arrayList.add(567);
arrayList.add(234);
arrayList.add(789);
arrayList.add(123);
System.out.println("ArrayList=" + arrayList);
System.out.println("-------------------------------------");
List<Integer> linkedList = new LinkedList<Integer>();
linkedList.add(345);
linkedList.add(567);
linkedList.add(234);
linkedList.add(789);
linkedList.add(123);
System.out.println("LinkedList=" + linkedList);
}
}
ArrayList数据结构
- 数据在ArrayList集合中是以数组结构来组织的。
-
所有数据都是在一个连续的内存中存放,新添加的数据被放到数组最末端。
- 它可以保证数据的存放顺序符合其添加顺序
- 同时也可以访问指定位置的数据
-
基于下标访问ArrayList中的元素效率非常高,访问第1个元素和第n个元素的消耗基本相同
- 因为数组中的元素在内存中是连续存放的
- 可以基于第一个元素的内存地址,计算得到第n个元素的内存地址,然后使用该地址直接访问第n个元素
-
ArrayList底层的数组也是有长度限制的,当超过数组的长度时,ArrayList会自动进行扩容操作,每次扩容是原数组长度的1.5倍
-
ArrayList的一些原理:
-
当新创建ArrayList对象后,底层默认使用一个空数组
-
当第一次向ArrayList中添加元素时,会默认创建一个长度为10的新数组,用于保存元素
-
当ArrayList底层的数组满了之后,会自动执行扩容操作,新的数组长度为原数组的1.5倍,会创建新数组,并将原数组的成员复制到新数组中
-
ArrayList的动态扩容会造成较多的资源消耗,在实际开发中,应该尽量避免频繁的扩容,如何避免?
- 如果知道要添加多少个元素,在创建ArrayList时,可以使用它的带参构造器,直接指定底层数组的长度
-
List list=new ArrayList(1000); // 底层直接创建1个长度为1000的数组
* 这种操作也被称为:集合操作的一种最佳实践(Best Practices)
链表结构
LinkedList数据结构
- 数据在LinkedList集合中是以双向链表结构来存放的。双向链表的具有以下特点:
- 每个数据都是一个节点,各数据节点通过指针与(前后)相邻的节点相连接,从而形成一个(前后)双向链表
- 各数据节点可能位于不同的内存块,因此集合中的数据并非占用连续的内存区域
- 新添加的数据将被放到链表尾端,因此,它同样保证数据的存放顺序符合其添加顺序,同时也可以访问指定位置的数据
ArrayList与LinkedList比较
- ArrayList与LinkedList集合各有所长,可以在不同场合根据具体需求选用:
- ArrayList元素的检索(使用下标访问)速度高于LinkedList
- LinkedList因为内存的不连续性,更适合于大批量数据的存放和管理
- 可以规避ArrayList的动态扩容问题
- 如果在非末端插入/删除数据,LinkedList速度优于ArrayList
- 什么时候用ArrayList?什么时候用LinkedList?
- 明确知道要保存的元素的个数时,用ArrayList
- 需要频繁使用下标查找元素时,用ArrayList
- 需要频繁进行非末端元素的添加/删除操作时,用LinkedList
常用的Set集合实现类包括:
- HashSet:基于哈希(Hash) 算法来存放和管理集合中的数据
- TreeSet:使用排序二叉树数据结构来存放和管理数据,集合中的数据按其顺序自然排序存放
HashSet数据结构
-
在HashSet集合中,有一个用来存放数据对象的内部数组。
- 向集合中添加数据时,HashSet首先获取该数据对象的哈希值
- 然后通过哈希算法将该值换算为数组的下标索引
- 然后将此数据保存在下标所指的位置。
-
任何对象均有自己的哈希值,该值可通过调用对象的hashCode()方法(继承自Object类)来获得。
TreeSet数据结构
- TreeSet集合内部使用排序二叉树来存放和管理数据。
- 排序二叉树是一种能将数据按其大小顺序组织在一个树形结构上的数据结构。
- 排序二叉树具有以下特点:
- 树中的每个节点,除存放数据外,还有指向左、右子树节点的指针;
- 每个节点都是通过指针相互连接的,相连指针的关系都是父子关系;
- 所有左子树的节点数值都小于此节点的数值;
- 所有右节点的数值都大于此节点的数值。