<Java.JavaEE面试整理>(12) 对Collections FrameWork的理解(二)

本文深入探讨Java集合框架的关键概念,包括迭代器的工作原理、如何避免并发修改异常、列表迭代器的功能及其优势,并讨论了集合框架提供的灵活性、性能和稳健性。

<Java.JavaEE面试整理>(12) 对Collections FrameWork的理解(二)

 

++++++++++++++++++++++++++++++++++++++++++

真是抱歉,没有把那个<Java.JavaEE面试整理>(11) 对Collections FrameWork的理解(一)(以下简称"理解一")这样核心部分的内容放到频道首页来让更多的朋友看到,而只是把个英文原文放到这里.

应该说"理解一"更为值得关注.

为了答谢大家的支持,鄙人会将这段时间对这个Collection Framework的理解心得整理出来与大家交流.

++++++++++++++++++++++++++++++++++++++++++

 

这个话题所涉及到的问题很重要,先把英文的原话写在这时在,等过些天有时间了,再结合iterator设计模式好好研究这个问题.

 

Q. 为什么用Itetator时,会抛出ConcurrentModificationException这样的异常呢?
    Why do you get a ConcurrentModificationException when using an iterator? CO

    
Problem: The java.util Collection classes are fail-fast, which means that if one thread changes a collection while another
thread is traversing it through with an iterator the iterator.hasNext() or iterator.next() call will throw
ConcurrentModificationException.  Even the synchronized collection wrapper classes  SynchronizedMap and
SynchronizedList are only conditionally thread-safe, which means all individual operations are thread-safe but compound
operations where flow of control depends on the results of previous operations may be subject to threading issues.  
 
Collection<String> myCollection = new ArrayList<String>(10);
 
myCollection.add("123");
myCollection.add("456");
myCollection.add("789");
 
for (Iterator it = myCollection.iterator(); it.hasNext();) {
    String myObject = (String)it.next();
    System.out.println(myObject);  
    if (someConditionIsTrue) {
        myCollection.remove(myObject);  //can throw ConcurrentModificationException in single as  
                                        //well as multi-thread access situations.     
    }   
}  
 
Solutions 1-3:  for multi-thread access situation:
 
Solution 1: You can convert your list to an array with list.toArray() and iterate on the array. This approach is not
recommended if the list is large.
 
Solution 2: You can lock the entire list while iterating by wrapping your code within a synchronized block. This approach
adversely affects scalability of your application if it is highly concurrent.  
 
Solution 3: If you are using JDK 1.5 then you can use the ConcurrentHashMap and CopyOnWriteArrayList  classes,
which provide much better scalability  and the iterator returned by ConcurrentHashMap.iterator() will not throw
ConcurrentModificationException while preserving thread-safety. (这个倒是不错!)
 
Solution 4:  for single-thread access situation:
 
Use:             
         it.remove();       // removes the current object via the Iterator “it” which has a reference to  
                       // your underlying collection “myCollection”. Also can use solutions 1-3.   
                       
Avoid:    
        myCollection.remove(myObject); // avoid by-passing the Iterator. When it.next() is called, can throw  the exception      
                                                                           // ConcurrentModificationException
 
 
Note: If you had used any Object to Relational (OR) mapping frameworks like Hibernate, you may have encountered this
exception “ConcurrentModificationException”  when you tried to remove an object from a collection such as a java.util Set
with the intention of deleting that object from the underlying database. This exception is not caused by Hibernate but
rather caused by your java.util.Iterator (i.e. due to your it.next() call). You can use one of the solutions given above.      
 
 
Q. What is a list iterator?  
 
The java.util.ListIterator is an iterator for lists that allows the programmer to traverse the list in either direction (i.e.
forward and or backward) and modify the list during iteration.
 

What are the benefits of the Java Collections Framework? Collections framework provides flexibility, performance,
and robustness.   
 
    .  Polymorphic algorithms – sorting, shuffling, reversing, binary search etc.  
    .  Set algebra - such as finding subsets, intersections, and unions between objects.  
    .  Performance - collections have much better performance compared to the older Vector and Hashtable classes with
the elimination of synchronization overheads.
    .  Thread-safety - when synchronization is required, wrapper  implementations are provided for temporarily
synchronizing existing collection objects. For J2SE 5.0 use java.util.concurrent package.
    .  Immutability - when immutability is required wrapper implementations are provided for making a collection
immutable.  
    .  Extensibility - interfaces and abstract classes provide an excellent starting point for adding functionality and
features to create specialized object collections.  
 
 
Q. What are static factory methods? CO
 
Some of the above mentioned features like searching, sorting, shuffling, immutability etc are achieved with
java.util.Collections class and java.util.Arrays utility classes.  The great majority of these implementations are provided
via  static factory methods in a single, non-instantiable (i.e. private constrctor) class. Speaking of  static factory
methods, they are an alternative to creating objects through constructors. Unlike constructors, static factory methods are
not required to create a new object (i.e. a duplicate object) each time they are invoked (e.g. immutable instances can be
cached) and also they have a more meaningful names like valueOf, instanceOf, asList etc. For example:
 
Instead of:
String[] myArray = {"Java", "J2EE", "XML", "JNDI"};
for (int i = 0; i < myArray.length; i++) {
     System.out.println(myArray[i]);
}
 
You can use:
String[] myArray = {"Java", "J2EE", "XML", "JNDI"};
System.out.println(Arrays.asList(myArray)); //factory method Arrays.asList(…)
 
 
For example:  The following static factory method (an alternative to a constructor) example converts a boolean primitive
value to a Boolean wrapper object.

public static Boolean valueOf(boolean b) {
    return (b ? Boolean.TRUE : Boolean.FALSE)   
}

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>KuCun2</groupId> <artifactId>KuCun2</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>KuCun2</name> <description/> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.12.RELEASE</version> <!-- 请根据需要选择版本 --> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <webVersion>4.0</webVersion> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <protobuf.version>3.21.12</protobuf.version> </properties> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.servlet.jsp.jstl</artifactId> <version>1.2.4</version> </dependency> <!-- Spring Boot Starter Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- MySQL Connector --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> <exclusions> <exclusion> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> </exclusion> </exclusions> </dependency> <!-- Optional: Lombok for reducing boilerplate code --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency> <!-- Jackson Databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- Jackson Core --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> </dependency> <!-- Jackson Annotations --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <exclusions> <exclusion> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>${protobuf.version}</version> </dependency> <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> <version>1.30</version> <!-- 统一版本号 --> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build> </project> public AuthenticationSuccessHandler ajaxAuthenticationSuccessHandler() { return (request, response, authentication) -> { // 强制创建服务端会话 request.getSession(true); // 构建安全响应数据 Map<String, Object> responseData = new HashMap<>(); responseData.put("sessionId", request.getSession().getId()); responseData.put("userInfo", Collections.unmodifiableMap(new HashMap<>() {{ put( "displayName", ((CustomUserDetails)authentication.getPrincipal()).getName()); put("roleLevel", ((CustomUserDetails)authentication.getPrincipal()).getRole()) }})); // 统一返回JSON格式 response.setContentType(MediaType.APPLICATION_JSON_VALUE); new ObjectMapper().writeValue(response.getWriter(), responseData); }; }request报红
05-30
<think>好的,我现在需要解决用户的问题:在提供的Java代码中,`request`变量报红,即无法解析。用户已经给出了相关的pom.xml配置和代码片段,我需要分析可能的原因并提供解决方案。首先,用户提到在`ajaxAuthenticationSuccessHandler`方法中,`request`参数报红,无法解析。这可能是因为缺少相关的ServletAPI依赖,或者导入的包不正确。但根据用户提供的pom.xml,已经包含了`javaee-api`依赖,并且作用域为provided,所以理论上应该没有问题。但可能还有其他原因。接下来,我需要检查pom.xml中的依赖是否正确。用户使用了SpringBoot2.3.12,并且引入了`javaee-api`8.0,作用域为provided。同时,还有Tomcat的starter依赖,作用域也是provided。这些应该提供了Servlet相关的类。但需要注意,JakartaEE和JavaxEE的包名不同,可能导致导入错误。 另一个可能性是IDE的问题,比如Maven依赖没有正确下载或缓存导致的问题。用户可能需要重新加载Maven项目,或者检查IDE的设置。此外,用户代码中的`request.getSession(true)`是否正确导入了`HttpServletRequest`?需要确认导入语句是否为`javax.servlet.http.HttpServletRequest`,而不是其他包。还可能存在依赖冲突。例如,项目中可能有多个不同版本的ServletAPI,导致编译器无法正确识别。需要检查依赖树,排除重复的依赖。 最后,考虑是否因为Spring Boot的版本与Servlet API版本不兼容。SpringBoot2.3.x默认使用的是Servlet4.0,而`javaee-api`8.0应该对应,但可能存在其他问题。综合这些可能性,我需要逐一排查,给出解决方案。</think>在Spring Boot项目中`request`参数报红的根本原因是**Servlet API依赖作用域冲突**和**包导入不完整**。以下是具体解决方案: ### 解决方案 1. **修正Servlet依赖配置**: ```xml <!-- 替换原有javaee-api依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> ``` 2. **显式添加Spring Web依赖**: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> ``` 3. **验证导入语句**: ```java // 确保包含正确的导入 import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; ``` ### 问题根源分析 1. **依赖冲突**: - `javaee-api`包含完整JavaEE规范,但可能与Spring Boot内嵌容器的Servlet API产生冲突 - 使用`javax.servlet-api`更精准地提供Servlet规范支持 2. **作用域问题**: ```xml <!-- 错误配置 --> <scope>provided</scope> <!-- 同时出现在多个依赖 --> <!-- 正确配置 --> <scope>provided</scope> <!-- 仅用于容器提供的API --> ``` 3. **版本不匹配**: - Spring Boot 2.3.x默认使用Servlet 4.0 - `javaee-api 8.0`对应Jakarta EE 8,而实际需要Javax的Servlet API ### 完整配置示例 ```xml <dependencies> <!-- Servlet API --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- Spring Security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- Spring Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> ``` ### 附加验证步骤 1. 执行Maven命令清理缓存: ```bash mvn clean install -U ``` 2. IDE操作: - 右键项目 > Maven > Update Project - 检查Project SDK是否与POM的Java版本一致(此处为1.8) 3. 验证类路径: ```java public class ServletAPIVerifier { public static void main(String[] args) { try { Class.forName("javax.servlet.http.HttpServletRequest"); System.out.println("Servlet API加载成功"); } catch (ClassNotFoundException e) { System.out.println("Servlet API未找到"); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值