周报总结---集合、Spring--IOC和DI

5 篇文章 0 订阅
1 篇文章 0 订阅

集合

概念

  • 对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
  • 位置:java.util.*
  • 和数组区别
    • 数组长度固定,集合长度不固定。
    • 数组可以存储基本类型和引用类型,集合只能存储引用类型。

Collection体系集合

在这里插入图片描述

Collection父接口

  • 特点:代表一组任意类型的对象,无序、无下标。
  • 常用方法:
方法描述
boolean add(Object obj)添加一个对象数据
boolean addAll(Collection c)将一个集合中的所有对象添加到此集合中
void clear()清空此集合中的所有对象
boolean contains(Object o)检查此集合中是否包含o对象
boolean equals(Object o)比较此集合是否与指定对象相等
boolean isEmpty()判断此集合是否为空
boolean remove(Object o)在此集合中移除o对象
int size()返回此集合中的元素个数
Object[] toArray()将此集合转换成数组

注:遍历同时不能使用集合删除方法,否则出现并发修改异常,可使用迭代器的删除方法。
遍历方法:
1、增强for循环
2、迭代器

public class TestCollection2 {
	public static void main(String[] args) {
		//新建Collection对象
		Collection collection=new ArrayList();
		Student s1=new Student("张三", 20);
		Student s2=new Student("张无忌", 18);
		Student s3=new Student("王二", 22);
		//1添加数据
		collection.add(s1);
		collection.add(s2);
		collection.add(s3);
		System.out.println("元素个数:"+collection.size());
		System.out.println(collection.toString());
		//2删除
		//collection.remove(s1);
		//collection.remove(new Student("王二", 22));
//		collection.clear();
//		System.out.println("删除之后:"+collection.size());
		//3遍历
		//3.1 增强for
		System.out.println("-------增强for----");
		for (Object object : collection) {
			Student s=(Student)object;
			System.out.println(s.toString());
		}
		//3.2迭代器: hasNext()  next();  remove(); 迭代过程中不能使用使用collection的删除方法
		System.out.println("-------迭代器----");
		Iterator it=collection.iterator();
		while(it.hasNext()) {
			Student s=(Student)it.next();
			System.out.println(s.toString());
		}
		//4判断
		System.out.println(collection.contains(s1));
		System.out.println(collection.isEmpty());
		
	}
}

List接口及其实现类

List接口
  • 特点:有序、有下标、元素可以重复。
  • 常用方法:
方法描述
void add(int index, Object o)在index位置插入对象o。
boolean addAll(int index, Collection c)将一个集合中的元素添加到此集合中的index位置。
Object get(int index)返回集合中指定位置的元素。
List subList(int fromIndex, int toIndex)返回fromIndex和toIndex之间的集合元素。
  • 遍历方法:
    1、普通for循环
    2、增强for循环
    3、迭代器

案例

public class TestList {
	public static void main(String[] args) {
		//先创建集合对象
		List list=new ArrayList();
		//1添加元素
		list.add("苹果");
		list.add("小米");
		list.add(0, "华为");
		System.out.println("元素个数:"+list.size());
		System.out.println(list.toString());
		//2删除元素
		//list.remove("苹果");
//		list.remove(0);
//		System.out.println("删除之后:"+list.size());
//		System.out.println(list.toString());
		//3遍历
		//3.1使用for遍历
		System.out.println("-----3.1使用for遍历-----");
		for(int i=0;i<list.size();i++) {
			System.out.println(list.get(i));
		}
		//3.2使用增强for
		System.out.println("-----3.2使用增强for-----");
		for (Object object : list) {
			System.out.println(object);
		}
		//3.3使用迭代器
		Iterator it=list.iterator();
		System.out.println("-----3.3使用迭代器-----");
		while(it.hasNext()) {
			System.out.println(it.next());
		}
		//3.4使用列表迭代器 ,和Iterator的区别,ListIterator可以向前或向后遍历,添加、删除、修改元素
		ListIterator lit=list.listIterator();
		System.out.println("------使用列表迭代器从前往后-------");
		while(lit.hasNext()) {
			System.out.println(lit.nextIndex()+":"+lit.next());
		}
		System.out.println("------使用列表迭代器后往前-------");
		while(lit.hasPrevious()) {
			System.out.println(lit.previousIndex()+":"+lit.previous());
		}
		
		//4判断
		System.out.println(list.contains("苹果"));
		System.out.println(list.isEmpty());
		
		//5获取位置
		System.out.println(list.indexOf("华为"));
	}
}
List实现类
ArrayList
  • 数组结构实现,查询快、增删慢。

  • JDK1.2版本、线程不安全。

  • 遍历方式
    1、普通for循环
    2、增强for循环
    3、迭代器

LinkedList
  • 链表结构实现,增删快,查询慢。

  • JDK1.2版本、线程不安全。

  • 遍历方式
    1、普通for循环
    2、增强for循环
    3、迭代器

Vector(了解)

数组结构实现,查询快、增删慢。
JDK1.0版本,线程安全、运行效率比ArrayList较慢。

List集合体系总结
  • List:一个有序容器,所以可以允许重复的对象,可以插入多个null

  • ArrayList:底层是动态数组,默认是空数组,若存值则扩容至10,如果不够则按照1.5倍进行扩容

  • LinkedList:底层是采用双向链表

  • Vector:线程安全。底层是可扩展的对象数组,可以使用整数索引访问,并且Vector的大小可以根据需要增长或缩小

ArrayList、LinkedList、Vector的区别

  • ArrayList和Vector是基于数组实现,ArrayList线程不安全,速度快,Vector线程安全,速度慢。因为底层是数组所以查询、修改快,增删慢。
  • LinkedList底层是双向链表,线程不安全,增删快,查询修改慢
  • ArrayList和Vector是使用Object类型的数组存储,ArrayList扩容是1.5倍和Vector扩容是2倍,扩容实际上是将数组拷贝复制到另一个数组中

Set接口及其实现类

Set接口
  • 特点:无序、无下标、元素不可重复。
  • 方法:全部继承自Collection中的方法。
  • 遍历方法
    1、增强for循环
    2、迭代器
实现类
HashSet
  • 基于HashCode实现元素不重复。
  • 当存入元素的哈希码相同时,会用equals进行确认,结果为true,拒绝后者存入。
  • 遍历方法
    1、增强for循环
    2、迭代器
LinkedHashSet
  • 链表实现的HashSet,按照链表进行存储,即可保留元素的插入顺序。
TreeSet
  • 基于排列顺序实现元素不重复。
  • 实现了SortedSet接口,对集合元素自动排序。
  • 元素对象的类型必须实现Comparable接口,指定排序规则(自然排序)。
  • 通过CompareTo方法确定是否为重复元素。
  • 遍历方法
    1、增强for
    2、迭代器
    注:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素。

Comparable接口CompareTo方法

public class Person implements Comparable<Person>{
	private String name;
	private int age;
	public Person() {
		// TODO Auto-generated constructor stub
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	//先按姓名比,然后再按年龄比
	@Override
	public int compareTo(Person o) {
		int n1=this.getName().compareTo(o.getName());
		int n2=this.age-o.getAge();
		return n1==0?n2:n1;
	}
}

Comparator接口

public class TestComparator {
	public static void main(String[] args) {
		//创建集合,并指定比较规则
		TreeSet<Person> persons=new TreeSet<>(new Comparator<Person>() {
			@Override
			public int compare(Person o1, Person o2) {
				int n1=o1.getAge()-o2.getAge();
				int n2=o1.getName().compareTo(o2.getName());
				return n1==0?n2:n1;
			}
		});
		
		Person p1=new Person("xyz", 20);
		Person p2=new Person("hello", 22);
		Person p3=new Person("zhangsan", 25);
		Person p4=new Person("lisi", 25);
		
		persons.add(p1);
		persons.add(p2);
		persons.add(p3);
		persons.add(p4);
		System.out.println(persons.toString());
	}
}
set体系总结
  • 不允许重复对象。无序容器,无法保证每个元素的存储顺序,TreeSet通过 Comparator 或者 Comparable 维护了一个排序顺序。因为是无序的所以只允许一个 null 元素。

  • TreeSet保证对象的有序性

    • 数据会按自然排序(可以理解为从小到大排序)
    • 不可存储null
    • 数据不可重复
    • 非线程安全
    • TreeSet底层依赖于TreeMap,TreeMap的数据结构是二叉树(红黑树),由底层数据结构决定了
    • TreeSet中元素有序且唯一。
    • 使用TreeSet时,如果添加对象的话,就必须去实现Comparable接口,当然也可以实现Comparator接口来保证对象的有序性。
  • HashSet 的实现原理

    • HashSet底层使用了哈希表来支持的,特点:存储快, 底层由HashMap实现
    • 往HashSet添加元素的时候,HashSet会先调用元素的hashCode方法得到元素的哈希值 ,然后通过元素的哈希值经过移位等运算,就可以算出该元素在哈希表中的存储位置。
    • 如果算出的元素存储的位置目前没有任何元素存储,那么该元素可以直接存储在该位置上
    • 如果算出的元素的存储位置目前已经存在有其他的元素了,那么还会调用该元素的equals方法与该位置的元素再比较一次,如果equals方法返回的是true,那么该位置上的元素视为重复元素,不允许添加,
      如果返回的是false,则允许添加 。
  • Hash碰撞以及常见的解决方案

Hash碰撞 : 对象Hash的前提是实现equals()和hashCode()两个方法,那么HashCode()的作用就是保证对象返回唯一hash值,但当两个不同对象计算值一样时,这就发生了碰撞冲突。

解决方案:

  • 开放地址法(再散列法)开放地执法有一个公式:Hi=(H(key)+di) MOD m i=1,2,…,k(k<=m-1)其中,m为哈希表的表长。di 是产生冲突的时候的增量序列。如果di值可能为1,2,3,…m-1,称线性探测再散列。
    如果di取1,则每次冲突之后,向后移动1个位置.如果di取值可能为1,-1,2,-2,4,-4,9,-9,16,-16,…kk,-kk(k<=m/2),称二次探测再散列。如果di取值可能为伪随机数列。称伪随机探测再散列。
  • 再哈希法Rehash当发生冲突时,使用第二个、第三个、哈希函数计算地址,直到无冲突时。
    缺点:计算时间增加。
    比如上面第一次按照姓首字母进行哈希,如果产生冲突可以按照姓字母首字母第二位进行哈希,再冲突,第三位,直到不冲突为止.这种方法不易产生聚集,但增加了计算时间。
  • 链地址法(拉链法)将所有关键字为同义词的记录存储在同一线性链表中.基本思想:将所有哈希地址为i的元素构成一个称为同义词
    链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。

Map体系集合

在这里插入图片描述

Map接口及其实现类

Map接口
  • 特点
    • 用于存储任意键值对(Key-Value)。
    • 键:无下标、不可以重复(唯一)。
    • 值:无下标、可以重复 。
  • 常用方法
方法名描述
V put(K key,V value)将对象存入到集合中,关联键值。key重复则覆盖原值。
Object get(Object key)根据键获取对应的值。
Set keySet()返回所有key。
Collection values()返回包含所有值的Collection集合。
Set<Map.Entry<K,V>> entrySet()键值匹配的Set集合。
  • 遍历方法
    1、entrySet()方法
    2、keySet()

例子

public class TestMap {
	public static void main(String[] args) {
		//创建Map集合
		Map<String, String> map=new HashMap<>();
		//1添加元素
		map.put("cn", "中国");
		map.put("uk", "英国");
		map.put("usa", "美国");
		map.put("cn", "zhongguo");
		
		System.out.println("元素个数:"+map.size());
		System.out.println(map.toString());
		
		//2删除
//		map.remove("usa");
//		System.out.println("删除之后:"+map.size());
		//3遍历
		//3.1使用keySet();
		System.out.println("------keySet()--------");
		//Set<String> keyset=map.keySet();
		for (String key : map.keySet()) {
			System.out.println(key+"-----"+map.get(key));
		}
		//3.2使用entrySet()方法
		System.out.println("------entrySet()-----");
		//Set<Map.Entry<String, String>> entries=map.entrySet();
		for (Map.Entry<String, String> entry : map.entrySet()) {
			System.out.println(entry.getKey()+"---------"+entry.getValue());
		}
		//4判断
		System.out.println(map.containsKey("cn"));
		System.out.println(map.containsValue("泰国"));
		
	}
}

实现类
HashMap
  • JDK1.2版本,线程不安全,运行效率快。
  • 允许用null 作为key或是value。
  • 存储结构:哈希表。
  • 遍历方法
    1、使用keySet()
    2、使用entrySet()
TreeMap
  • 实现了SortedMap接口(Map的子接口),可以对key自动排序,Key需实现Comparable接口。
  • 遍历方法
    1、使用keyset
Hashtable :
  • JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value。
Properties :
  • Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。
Map体系总结
  • Map: 与Collection并列,用来存储具有映射关系(key-value)的数据
    • HashMap:哈希表结构存储数据,key值可以为null
    • TreeMap:红黑树算法的实现
    • HashTable:哈希表实现,key值不可以为null
    • Properties:HashTable的子类,键值对存储数据均为String类型,主要用来操作以.properties
      结尾的配置文件。
  • 存储数据是以key,value对进行存储,其中key值是以Set集合形式存储,唯一且不可重复。
    value是以Collection形式存储,可以重复。
  • 优缺点
    • Map不是collection的子接口或者实现类。Map是一个接口。
    • Map 的 每个 Entry 都持有两个对象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。
    • TreeMap 也通过 Comparator 或者 Comparable 维护了一个排序顺序。
    • Map 里你可以拥有随意个 null 值但最多只能有一个 null 键。
    • Map 接口最流行的几个实现类是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用)
  • HashTable、HashMap、TreeMap的区别
    • Hashtable、HashMap、TreeMap都实现了Map接口,使用键值对的形式存储数据和操作数据。
    • Hashtable是java早期提供的,方法是同步的(加了synchronized)。key和value都不能是null值。
    • HashMap的方法不是同步的,支持key和value为null的情况。行为上基本和Hashtable一致。由于Hashtable是同步的,性能开销比较大,一般不推荐使用Hashtable。通常会选择使用HashMap。
    • HashMap进行put和get操作,基本上可以达到常数时间的性能
    • TreeMap是基于红黑树的一种提供顺序访问的Map,和HashMap不同,它的get或put操作的时间复杂度是O(log(n))。具体的顺序由指定的Comparator来决定,或者根据键key的具体顺序来决定。
  • HashMap的底层数据存储结构

JDK1.7采用 : 数组 + 链表结构
JDK1.8采用 : 数组 + 链表 + 红黑树
红黑树:jdk1.8最重要的就是引入了红黑树的设计,当hash表的单一链表长度超过 8 个的时候,链表结构就会转为红黑树结构。

  • HashMap的底层数据存储结构为哈希表加红黑树。实现过程如下
    • 调用HashMap的无参构造方法,加载因子loadFactor赋值0.75,table数组是空。
    • 当添加第一个元素时,创建长度16的数组,threshold=12。
    • 当‘链表长度大于等于8时,并且数组长度大于等于64时,链表调整红黑树
    • 当红黑树的节点个数小于6时,调整为链表
    • 当HashMap的容量超出阈值时,扩容为原来大小的2倍,减少元素的移动,提高效率。
  • HashMap链表和红黑树转化时机
    当链表长度超过8且哈希表容量大于64,会将链表转化为红黑树。而当红黑树的大小小于6,
    则由树转化为链表。

Spring—IOC和DI

Spring主要是三种方式
1、xml配置文件
2、注解开发
3、xml+注解开发
概念:Spring是分层的轻量级开源框架。以IOC(控制反转)和 AOP(面向切面编程)为内核。

IOC

是一种设计思想。它的目的是指导我们设计出更加松耦合的程序。
一句话来说就是:bean的创建和销毁交给spring容器管理。

xml配置文件方式

步骤分析及代码实现
  1. 导入依赖(spring-context)
<!--导入spring的ioc核心依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.5.RELEASE</version>
</dependency>
  1. 编写UserDao接口及其实现类
  2. 编写一个spring的配置文件(名字任意)
    • 通过bean标签配置dao
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userDao" class="cn.dao.impl.UserDaoImpl"/>
</beans>
  1. 编写测试代码
    • 获取spring容器(工厂)对象
    • 通过工厂对象获取dao的对象
    • 调用save方法
public class TestHelloIOC {
    @Test
    public void testIocHello(){
        //- 获取spring容器(工厂)对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //- 通过工厂对象获取dao的对象
        UserDao userDao = (UserDao) context.getBean("userDao");

        //- 调用save方法
        userDao.save();
    }
}

Spring的API体系

主要关注两个BeanFactoryApplicationContext
在这里插入图片描述

BeanFactory和ApplicationContext的关系
  • BeanFactory是ApplicationContext的父接口
  • BeanFactory初始化配置文件中单实例对象的时机:每次调用getBean的时候才创建对应的对象
  • ApplicationContext初始化配置文件中单实例对象的时机:在工厂对象初始化完成的时候已经创建好了
实现类
* FileSystemXmlApplicationContext【了解】
	功能:从指定磁盘目录加载xml配置文件,创建spring的ioc容器

* ClassPathXmlApplicationContext
	功能:从类路径下加载xml配置文件,创建spring的ioc容器
	
* AnnotationConfigApplicationContext
	功能:加载注解配置类,创建spring的ioc容器

Spring配置文件

配置文件的名字可以放在任意位置,名字任意

Bean标签
<!--
        bean:将配置的对象加入spring容器管理
            id属性(name属性):给bean起个名字,要保证当前项目中唯一
            class属性:配置对象对应的全限定类名(类且有无参构造器)

            其他的配置:
            scope属性:配置对象的作用范围(单实例还是多实例等)
                常见俩值:
                    singleton:默认值,单实例对象
                    prototype:多实例对象,一般用不上,struts2框架中action是多实例
            init-method属性:指定对象创建成功之后要执行的方法(初始化操作),我们一般用不上,框架底层使用
            destroy-method属性:指定对象销毁之前要执行的方法(销毁操作),我们一般用不上,框架底层使用

    -->
<bean id="userDao" class="cn.dao.impl.UserDaoImpl" scope="singleton" init-method="init" destroy-method="dest"/>

DI依赖注入

set方法注入

<!--依赖注入:set-->
<bean id="userService" class="cn.service.impl.UserServiceImpl">
    <!--property:使用set方式给属性进行赋值操作
                name属性:需要赋值的属性名称
                ref属性:属性类型为引用类型且在spring容器中存在,值就是在spring容器中bean对象的名字
                value属性:属性类型为简单类型(包含基本类型、包装类及string类型)
        -->
    <property name="userDao" ref="userDao"/>
</bean>

构造方法注入

<!--依赖注入:构造器方法-->
<bean id="userService1" class="cn.service.impl.UserServiceImpl">
     <!--
            constructor-arg:使用构造器进行赋值操作
                name属相:构造方法中形参的名字
                value属性:给简单类型进行赋值
                ref属性:给引用类型进行赋值操作,值就是spring容器中对象的id值
        -->
    <constructor-arg name="age" value="12"/>
    <constructor-arg name="name" value="tom"/>
    <constructor-arg name="userDao" ref="userDao"/>
</bean>

p命名空间注入(了解)

本质上也是set方法,在此基础上进行了简化

步骤:

  1. 需要在spring的配置文件中引入p名称空间
  2. 在需要注入的bean标签中通过 p:属性=“” 或者 p:属性-ref=""方式注入
    在这里插入图片描述
<!--p名称空间注入-->
<bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource"
      p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql:///travel"
      p:username="root" p:password="1234"/>

依赖注入的数据类型

  • 普通数据类型
    通过标签的value属性注入数据

  • 引用数据类型
    通过标签的ref属性注入数据

  • 集合数据类型

注解开发

Spring—IOC和DI注解开发

个人对Spring理解看法

Spring是一个轻量级框架,使用Spring极大的方便了我们对程序的开发,原因:

  • 不用我们自己手动频繁创建对象和管理对象
    • 因为spring替我们创建和管理了对象,方便我们更好的关心逻辑代码方面的开发
  • spring增加了横向的开发(AOP)
    • 对于oop来说我们更多地是一种纵向的开发,相当于是一层叠一层的开发
    • 但是对于很多时候,比如说要运行日志记录这些,需要横向抽取代码的时候,oop就无法满足,这个时候需要AOP来帮助实现
  • spring的核心就是IOC和AOP
  • 配置文件和注解是可以相互替换,相等价的

spring对于我个人来说极大地方便了开发,减少了代码的耦合,但是他也带来了一个很麻烦的事情就是配饰文件太多,太麻烦了。对于spring的开发最好的方法就是使用配置文件+注解的方式开发

两周学习出现的问题

导入jdk8的源码包到idea中失败

下两周计划

1、解决导入jdk8的源码包到idea中失败
2、复习spring框架AOP、mybatis
3、spring注解学习
若上面完成可完成下面的
3、mybatis源码阅读
4、springmvc框架

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值