集合与泛型总结

集合与泛型总结

一、集合:就像是一种容器,用于存储、获取和操作对象的容器。

1. 数组的弊端
①数组的长度不可变  ②没有提供可以查询数组中有效元素个数的方法

2.集合的特点
①集合的长度是可变的
②集合可以存储任意类型的对象
③集合只能存储对象

3.集合框架
java.util.Collection 接口: 是集合框架的根接口
|— java.util.List 接口: 是有序的,可以重复的。因为List体系下都具有索引值
|—ArrayList:存储元素采用的是数组结构。 在查询操作多时选择
|—LinkedList:存储元素采用的是链表结构。 在增删操作多时选择
|—Vector:
|— java.util.Set 接口: 无序的,不允许重复的。
|—HashSet:是Set接口的典型实现类。
采用哈希算法:先比较对象hashCode值,若hashCode值存在,再通过equals() 方法比较对象的内容
若hashCode值不存在,直接存储元素到集合中
注意:重写hashCode方法和equals方法二者要保持一致!
|—LinkedHashSet: 相较于HashSet多了链表结构。因为多了链表结构维护元素的顺序,以至于我们感觉像是按照添加的顺序添加
,遍历操作多时选择。
|—TreeSet:拥有自己特有排序方式
自然排序(Comparable接口):
①需要添加到Treeequals()Set集合的类实现Comparable接口
②重写compareTo(Object obj)
定制排序(Comparator接口):
①编写类实现Comparator接口
②重写 compare(Object o1, Object o2) 方法
③将实现类的实例作为参数,传递给TreeSet的构造器

二、集合的遍历
1. 使用增强for循环

List<String> list = new ArrayList<String>();

for(String str : list){

}

2. 使用Iterator迭代器
//①获取当前集合的Iteratror迭代器
Iterator<String> it =  list.iterator();

//②根据 hasNext()  和 next() 方法遍历集合元素
while(it.hasNext()){
String str = it.next();
}

三、java.util.Map 接口: 是存储一对对象的集合。具有key(键)-value(值)对映射关系的集合。key不允许重复,value可以重复
|—HashMap :是Map接口的典型实现类
|—LinkedHashMap:相较于HashMap多了链表结构维护元素的顺序
|—TreeMap : 根据TreeMap中的key进行排序
①自然排序  Comparable
②定制排序  Comparator
|—Hashtable: 是一个古老的实现,线程安全的,所以效率低
|—Properties: 用于操作属性文件。属性文件中 key 和 value 都是字符串

1.读取属性文件:【hello.properties】
如:

//①创建Properties对象
Properties props = new Properties();

//②加载指定属性文件
props.load(new FileInputStream(“hello.properties”));

//③读取属性文件内容
String user = props.getProperty(“user”);

2. Map的遍历:
Map<String, Integer> map = new HashMap<String, Integer>();
//①获取Map中所有的key组成Set
Set<String> set = map.keySet();

//②获取Map中所有的value组成的 Collection
Collection<Integer> coll = map.values();

//③获取Map中的一个内部类Entry组成Set
Set<Entry<String, Integer>> entrySet = map.entrySet();

Iterator<Entry<String, Integer>> it = entrySet.iterator();
while(it.hasNext()){
Entry<String, Integer> entry = it.next();
String key = entry.getKey();
Integer value = entry.getValue();
}

for(Entry<String, Integer> entry : entrySet){
String key = entry.getKey();
Integer value = entry.getValue();
}

四、用于操作集合的工具类: Collections

reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
void copy(List dest,List src):将src中的内容复制到dest中
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值

五、泛型:
为什么使用泛型:若不使用泛型,说明集合中可以添加任意类型的对象。若需要具体到某一个类型,需要强制类型转换。可能发生 ClassCastException

List list = new ArrayList();
list.add(“AA”);
list.add(123);

for(Object obj : list){
String str = (String)obj;
}

1. 在集合中使用泛型
2. 自定义泛型类、接口、方法
3. 通配符

如:
//自定义泛型类
class DAO<T>{

public void add(T t){

}

//自定义泛型方法
public <E> E get(E e){

}

}

struts值栈

struts值栈

1.提出问题

     为什么${requestScope.message }能够获取到数据?
     表面上是从请求域中获取的,但通过查看StrutsRequestWrapper类的getAttribute()方法的源码发现,其实不是从请求域中获取的,而是在查询了请求域之后,没有找到数据,进而从ValueStack对象中找到的目标对象。
2.ValueStack概述
     ①作用:是Struts2为每一个request准备的一个临时数据的存储空间。
     ②值栈对象内部保存数据的两个重要容器
          [1]对象栈:CompoundRoot root;
          [2]Map栈:transient Map<String, Object> context;
Tip:transient 表示当前成员变量不参与序列化
3.ValueStack对象获取
     ①通过ActionContext对象获取
     ②从请求域中读取
4.对象栈
     ①CompoundRoot
     ②继承自ArrayList,是使用List实现的一个堆栈数据结构。
5.Map栈
     ①本质
6.OGNL表达式
     ①OGNL也是Apache基金会组织下面commons项目中的子项目。
     ②对象图导航语言。能够以表达式的形式获取以前需要通过对象导航得到的数据。
          department.getEmp().getAddress().getCity();
          department.emp.address.city
          类似于jQuery选择器和Xpath在各自领域中的作用,都是为了简化查询而生的。
     ③读取对象栈数据
          [1]使用方括号指定索引时,表示从索引位置开始向下查找,找到就返回,找不到返回null
          [2]如果省略了方括号,则表示从栈顶开始查找
     ④读取Map栈数据
          [1]Map栈中包含的常用的内容
               封装请求域数据的Map
               封装Session域数据的Map
               封装Application域数据的Map
               封装请求参数数据的Map
               特殊Map:attr——在各个属性域中按从小到大的顺序查找属性
                    org.apache.struts2.util.AttributeMap
          [2]语法
               #key.属性名
数据 读取方式
封装请求域数据的Map #request.属性名
封装Session域数据的Map #session.属性名
封装Application域数据的Map #application.属性名
封装请求参数数据的Map #parameters.属性名
特殊Map:attr #attr.属性名
          [3]如果key中包含特殊符号,可以使用方括号引用这个键,这一点和EL表达式、JSON格式的处理方式是一致的。

struts声明式异常处理

struts声明式异常处理

1     基本思想
Struts2声明式异常处理的基本思想,就是通过配置的方式在捕获到指定类型的异常对象后,由com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor拦截器将异常信息保存到值栈中,进而通过OGNL表达式在页面上根据需要显示异常信息。

2     异常处理器对象
Struts2捕获到已声明的异常信息后,使用异常处理器com.opensymphony.xwork2.interceptor.ExceptionHolder对象封装异常信息,并将这个对象压入值栈中对象栈栈顶。异常处理器对象包含两个属性
①exceptionStack:异常的堆栈信息
②exception:异常对象本身
3     两个级别
3.1     Action级
<!– 声明了异常处理方式的Action –>
<action name=”daoDanAction” class=”com.atguigu.exception.action.DaoDanAction”>
<!– 如果在当前Action执行过程中捕获到如下异常,则前往errorMsg定义的result –>
<exception-mapping result=”errorMsg” exception=”java.lang.ArithmeticException”>
</exception-mapping>
<!– 没有捕获到异常时前往的页面 –>
<result>/good.jsp</result>
<!– 定义一个用于显示异常信息的result –>
<result name=”errorMsg”>/makeException.jsp</result>
</action>

3.2     全局
<!– 定义全局都能够引用的result信息 –>
<global-results>
<result name=”globalError”>/globalMsg.jsp</result>
</global-results>

<!– 在整个项目的范围内,如果捕获到了下面声明的异常,则跳转到指定的result –>
<global-exception-mappings>
<exception-mapping result=”globalError” exception=”java.lang.Exception”>
</exception-mapping>
</global-exception-mappings>
当捕获到一个异常对象时,如果同时存在Action和全局两种级别的映射信息,则优先使用Action级别。

struts模型驱动

struts模型驱动

1.理论知识

     ①请求参数是如何注入到当前Action类中的?
          [1]通过当前Action类的setXxx()方法注入的
          [2]params拦截器负责注入请求参数
          [3]params拦截器并不是针对Action类的对象注入请求参数,而是从对象栈的栈顶开始,查找有没有和请求参数name属性值匹配的setXxx()方法,如果有,则将请求参数注入进去,如果没有则继续向下查找。
     ②拦截器和拦截器栈
          [1]params拦截器是Struts2内置的众多拦截器中的一个。
          [2]Struts2在执行目标Action的目标方法之前,会逐一的调用每一个拦截器。
          [3]具体流程
               (1)Struts2的核心Filter拦截到了浏览器发送的请求
               (2)为了能够在执行目标Action的目标方法需要创建Action的代理对象——ActionProxy
               (3)ActionProxy只负责宏观上的指挥调度,具体的工作是由ActionInvocation对象完成的
               (4)在对ActionInvocation对象进行初始化的时候会将目标Action的对象压入栈顶
               (5)ActionInvocation对象会逐一的调用拦截器栈中定义的每一个拦截器,这个调用是以递归的方式进行的
               (6)直到所有的拦截器全部执行完成,则调用目标Action的目标方法
          [4]所有的拦截器会以拦截器栈的形式组织到一起,它们调用的顺序就是它们在拦截器栈中的顺序
     提示:看源码,分析流程一定要亲手自己去操作。
2.问题一
     (1)描述:用于注入请求参数和回显表单的属性相关的代码和Book实体类中的代码有非常严重的冗余。
     (2)解决方案:借助Struts2提供的modelDriven拦截器
①让当前Action类实现ModelDriven接口
②实现getModel()方法
③让getModel()方法返回book对象
④modelDriven拦截器会将getModel()方法返回的book对象压入值栈的栈顶
⑤params拦截器会将请求参数注入到栈顶的book对象
⑥将当前Action类中的冗余代码删除
     (3)modelDriven拦截器工作原理
①在params拦截器之前执行
②在modelDriven拦截器执行时,会首先判断目标Action是否实现了ModelDriven接口
③如果实现了这个接口,则调用getModel()方法
④将getModel()方法的返回值压入值栈栈顶
⑤继续执行后面的拦截器
⑥直到执行到params拦截器时,值栈栈顶的对象是Book对象,所以请求参数就会注入到Book对象中
3.问题二
     ①描述:在执行edit操作时,对象栈顶部有两个Book对象,浪费内存
     ②解决方案:在edit()方法中使用Dao中取出的Book对象给this.book赋值
 
4.问题三
     ①描述:不能实现表单回显,栈顶的对象并不是从Dao中取出的
     ②解决方案:使用从Dao中取出的Book对象逐个的给this.book指向的对象赋值、
 
5.问题四
     ①描述:逐个赋值很繁琐,而且从Dao中取出的本身就是一个可以用于回显的Book对象,现在浪费
     ②解决方案:在getModel()方法中查询Dao,将得到的对象返回
     ③将当前默认的拦截器栈修改为paramsPrepareParamsStack
< default-interceptor-ref name=“paramsPrepareParamsStack”/>
6.问题五
     ①描述:执行save操作时,没有bookId请求参数,不能从Dao中获取到Book对象,执行save()方法时有空指针异常
     ②解决方案
          [1]判断如果没有bookId时,给this.book赋值一个new Book()
          [2]判断如果有bookId时,给this.book赋值从Dao中取出的Book对象
7.问题六
     ①描述:在执行delete操作时,有bookId,会查询Dao,但delete操作不需要查询Dao,浪费资源
     ②解决方案:借助prepare拦截器为每一个Action方法量身定制this.book的值
          [1]实现Preparable接口
          [2]为每一个有需要的Action方法准备一个prepareXxx()方法
          [3]在prepareXxx()方法中给this.book赋值合适的book对象
          [4]修改getModel()方法
     ③拦截器执行的顺序:params→prepare→modelDriven→params
     ④prepare拦截器工作原理
          [1]检查目标Action中是否有带前缀的方法,例如:prepareSave()方法
          [2]如果有,则执行前缀方法
          [3]根据alwaysInvokePrepare变量的值决定是否要调用Action类中的prepare()方法
               true:执行
               false:不执行
8.问题七
     ①描述:默认情况下prepare()方法一定会执行
     ②解决方法:修改prepare拦截器的参数,将alwaysInvokePrepare变量的值设置为false
<!– 修改prepare拦截器的alwaysInvokePrepare值 –>
<interceptors>
     <!– 自定义拦截器栈的名字 –>
<interceptor-stack name= “myStack”>
     <!– 引用需要用到的拦截器或拦截器栈 –>
     <interceptor-ref name=“paramsPrepareParamsStack”>
           <!– 设置具体拦截器的属性值 –>
               <param name=“prepare.alwaysInvokePrepare” >false </param>
           </interceptor-ref>
     </interceptor-stack >
</interceptors>
 
<!– 指定当前使用的默认拦截器栈是上面自定义的拦截器栈 –>
<default-interceptor-ref name= “myStack”/>

 

struts自定义拦截器

struts自定义拦截器

1.拦截器

     作用:在Action方法执行之前或之后,进行一些特定的处理操作,并根据处理的结果决定是“放行”还是转到其他位置。(放行:继续执行后续的拦截器或目标Action方法)。
2.自定义拦截器
     ①需求
          [1]在拦截器中获取当前环境相关的资源
               ●目标Action对象
               ●值栈ValueStack对象
               ●Web资源
               ●ActionContext对象
               ……
          [2]控制拦截器执行走向
               ●执行后续拦截器或目标Action方法:invocation.invoke()
               ●执行指定的result:return “指定的result的name值”;
          [3]能够通过修改拦截器参数的方式对拦截器的行为进行定制
     ②实现步骤
          [1]创建实现类,扩展自已有的API
          [2]注册实现类
          [3]使用