【java总结】集合框架(精选3篇)
【java总结】集合框架 篇1
【java总结】集合框架
Collection是集合框架层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。Collection接口下有最常用的接口为List跟Set。需要注意的是,Map并没有实现Collection接口。
List接口实现类ArrayList 优点:类似数组的形式进行存储,因此它的随机访问速度极快。缺点:不适合于在线性表中间需要频繁进行插入和删除操作。因为每次插入和删除都需要移动数组中的元素,它是用数组存储元素的,这个数组可以动态创建,如果元素个数超过了数组的容量,那么就创建一个更大的新数组,并将当前数组中的所有元素都复制到新数组中。[html] view plain copy public class ArrayListTest {
public static void main(String[] args){
List
arrayList.add(“Welcome”);
arrayList.add(“to”);
arrayList.add(“java”);
//把ArrayList变为数组相关的内容进行遍历
String[] strArray=new String[arrayList.size()];
arrayList.toArray(strArray);
for(int i=0;i //使用迭代器进行ArrayList遍历 Iterator while(iter.hasNext()){ System.out.println(iter.next()); } } } List接口实现类LinkedList 优点:适合于在链表中间需要频繁进行插入和删除操作。 缺点: 随机访问速度较慢。查找一个元素需要从头开始一个一个的找。此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作LinkedList是在一个链表中存储元素。[html] view plain copy public class LinkedListTest { public static void main(String[] args){ List //使用ForEach遍历linkedList String[] strArray2=new String[linkedList.size()]; linkedList.toArray(strArray2); for(int i=0;i //foreach遍历LinkedList for(String str:linkedList){ System.out.println(str); } //使用迭代器进行ArrayList遍历 Iterator while(iter.hasNext()){ System.out.println(iter.next()); } } } List接口实现类Vector: Vector使用了关键字synchronized将访问和修改向量的方法都变成同步的了,所以对于不需要同步的应用程序来说,类ArrayList比类Vector更高效。相同点: ①都继承于AbstractList,并且实现List接口 ②都实现了RandomAccess和Cloneable接口 ③都是通过数组实现的,本质上都是动态数组,默认数组容量是10 ④都支持Iterator和listIterator遍历 不同点: ①ArrayList是非线程安全,而Vector是线程安全的 ②容量增加方式不同,Vector默认增长为原来一倍,而ArrayList却是原来的一半+1 ③Vector支持通过Enumeration去遍历,而List不支持 [html] view plain copy public class VectorTest { public static void main(String[] args){ Vector for(int i = 0;i < 10;i++){ vector.add(i); } //直接打印 System.out.println(vector.toString()); //size() System.out.println(vector.size()); //contains System.out.println(vector.contains(2)); //总结:对比Vector的遍历方式,使用索引的随机访问方式最快,使用迭代器最慢 //iterator遍历 Iterator while(iterator.hasNext()){ System.out.print(iterator.next()+ “ ”); } //Enumeration遍历 Enumeration enu = vector.elements(); while(enu.hasMoreElements()){ System.out.println((Integer)enu.nextElement()); } //toArray Object[] objArr = vector.toArray(); System.out.println(“nobjArr:” + Arrays.asList(objArr)); Integer[] intArr = vector.toArray(new Integer[vector.size()]); System.out.println(“intArr:” + Arrays.asList(intArr)); //add vector.add(5); //remove vector.remove(5); System.out.println(vector); //containsAll System.out.println(vector.containsAll(Arrays.asList(5,6))); //addAll vector.addAll(Arrays.asList(555,666)); System.out.println(vector); //removeAll vector.removeAll(Arrays.asList(555,666)); System.out.println(vector); //addAll方法 vector.addAll(5, Arrays.asList(666,666, 6)); System.out.println(vector); //get方法 System.out.println(vector.get(5)); //set方法 vector.set(5, 55); System.out.println(vector.get(5)); //add方法 vector.add(0, 555); System.out.println(vector); //remove方法 vector.remove(0); System.out.println(vector); //indexof方法 System.out.println(vector.indexOf(6)); //lastIndexOf方法 System.out.println(vector.lastIndexOf(6)); //listIterator方法 ListIterator System.out.println(listIterator.hasPrevious()); //listIterator(index)方法 ListIterator System.out.println(iListIterator.previous()); //subList方法 System.out.println(vector.subList(5, 7)); //clear vector.clear(); System.out.println(vector); } } List接口实现类Stack 栈类,是Java2之前引入的,继承自类Vector。同样是线程同步的 [html] view plain copy public class StackTest { public static void main(String[] args){ Stack for(int i = 0;i < 10;i++){ stack.add(i); } System.out.println(stack); System.out.println(stack.peek()); stack.push(555); System.out.println(stack); System.out.println(stack.pop()); System.out.println(stack); System.out.println(stack.empty()); System.out.println(stack.search(6)); System.out.println(“stack遍历:”); while(!stack.empty()){ System.out.print(stack.pop()+ “ ”); } } } List接口总结:实际使用中我们需要根据特定的需求选用合适的类,如果 除了在末尾外不能在其他位置插入或者删除元素,那么ArrayList效率更高,如果需要经常插入或者删除元素,就选择LinkedList。 Set接口实现类HashSet: HashSet是Set接口最常见的实现类,其底层是基于hash算法进行存储相关元素的。HashSet中存储元素的位置是固定的(由hashCode决定),并且是无序的。Set集合中的去重和hashCode与equals方法相关。[html] view plain copy public class Num implements Comparable{ private int num; public Num(int num){ this.num=num; } @Override public int compareTo(Object o){ // TODO Auto-generated method stub Num x=(Num)o; if(num>x.num)return 1; else if(num==x.num)return 0; else return-1; } public String toString(){ return “num=”+num; } } [html] view plain copy public class HashSetTest { public static void main(String[] args){ Set hashSet.add(“hello”); hashSet.add(“world”); hashSet.add(“world”); //使用数组的方法遍历HashSet集合String[] strArray=new String[hashSet.size()]; strArray=hashSet.toArray(strArray); for(String str:strArray){ System.out.println(str); } //使用HashSet集合直接遍历 for(String str:hashSet){ System.out.println(str); } //用迭代器遍历HashSet集合Iterator while(iterator.hasNext()){ System.out.println(iterator.next()); } //无重写hashCode跟equals方法的类,不会自动根据类中的值进行去重 Set set2.add(new Num(1)); set2.add(new Num(3)); set2.add(new Num(2)); set2.add(new Num(3)); set2.add(new Num(3)); set2.add(new Num(6)); System.out.println(set2.size()); Iterator while(iterator2.hasNext()){ System.out.println(iterator2.next()); } } } Set接口实现类LinkedHashSet: LinkedHashSet继承HashSet,是用一个链表实现来扩展HashSet类,它支持对规则集内的元素排序。HashSet中的元素是没有被排序的,而LinkedHashSet中的元素可以按照它们插入规则集的顺序提取。[html] view plain copy public class LinkedHashSetTest { public static void main(String[] args){ Set linkedHashSet.add(“hello”); linkedHashSet.add(“world”); linkedHashSet.add(“world”); //使用数组的方法遍历HashSet集合String[] strArray=new String[linkedHashSet.size()]; strArray=linkedHashSet.toArray(strArray); for(String str:strArray){ System.out.println(str); } //使用HashSet集合直接遍历 for(String str:linkedHashSet){ System.out.println(str); } //用迭代器遍历HashSet集合Iterator while(iterator.hasNext()){ System.out.println(iterator.next()); } } } Set接口实现类TreeSet: TreeSet实现了Set接口,它与HashSet的区别主要在于TreeSet中的元素会按照相关的值进行排序。HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的,只不过Set用的只是Map的key。由于TreeMap需要排序,所以需要一个Comparator为键值进行大小比较.当然也是用Comparator定位的.如果创建时没有确定,那么就会使用key.compareTo()方法,这就要求key必须实现Comparable接口.TreeMap是使用Tree数据结构实现的,所以使用compare接口就可以完成定位了.注意:TreeSet是根据对象的CompareTo方法来去重的,如果CompaerTo返回0说明两个对象相等,不能同时存在于TreeSet中。 [html] view plain copy public class TreeSetTest { public static void main(String[] args){ Set treeSet.add(“d”); treeSet.add(“c”); treeSet.add(“b”); treeSet.add(“a”); //String实体类中实现Comparable接口,所以在初始化TreeSet的时候, //无需传入比较器 Iterator while(iterator.hasNext()){ System.out.println(iterator.next()); } Set treeSet2.add(new Num(1)); treeSet2.add(new Num(3)); treeSet2.add(new Num(2)); treeSet2.add(new Num(3)); treeSet2.add(new Num(3)); treeSet2.add(new Num(6)); System.out.println(treeSet2.size()); Iterator while(iterator2.hasNext()) { System.out.println(iterator2.next()); } TreeSet set.add(1111); set.add(2222); set.add(3333); set.add(4444); set.add(5555); System.out.println(set.first());// 输出第一个元素 System.out.println(set.lower(3333));//小于3333的最大元素 System.out.println(set.higher(2222));//大于2222的最大元素 System.out.println(set.floor(3333));//不大于3333的最大元素 System.out.println(set.ceiling(3333));//不小于3333的最大元素 System.out.println(set.pollFirst());//删除第一个元素 System.out.println(set.pollLast());//删除最后一个元素 System.out.println(set); } } Set接口区别于List接口在于: 所有Set中的元素实现了不重复,有点像数学中集合的概念,无序,不允许有重复的元素,最多允许有一个null元素对象 Map接口: Map接口储存一组成对的键-值对象,提供key(键)到value(值)的映射,Map中的key不要求有序,不允许重复。value同样不要求有序,但可以重复。 Map实现类HashMap 最常见的Map实现类,他的储存方式是哈希表,优点是查询指定元素效率高。HashMap采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当链表中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,HashMap采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。 无论什么情况HashMap中哈希表的容量总是2的n次方的一个数。并且有这样一个公式:当length=2^n时,hashcode &(length-1)== hashcode % length HashMap与Hashtable的区别: Hashtable实现Map接口,继承自古老的Dictionary类,实现一个key-value的键值映射表。任何非空的(key-value)均可以放入其中。区别主要有三点: 1.Hashtable是基于陈旧的Dictionary实现的,而HashMap是基于Java1.2引进的Map接口实现的; 2.Hashtable是线程安全的,而HashMap是非线程安全的,我们可以使用外部同步的方法解决这个问题。 3.HashMap可以允许你在列表中放一个key值为null的元素,并且可以有任意多value为null,而Hashtable不允许键或者值为null。 [html] view plain copy public class HashMapTest { public static void main(String[] args){ Map hashMap.put(“a”,1); hashMap.put(“b”,2); hashMap.put(“JAVA”,3); System.out.println(hashMap.get(“JAVA”)); //第一种遍历方法:普遍使用,二次取值 for(String key : hashMap.keySet()){ System.out.println(“key= ”+ key + “ and value= ” + hashMap.get(key)); } //第二种:通过Map.entrySet使用iterator遍历key和value Iterator while(iter.hasNext()){ System.out.println(iter.next()); } //第三种:通过Map.entrySet遍历key和value.推荐,尤其是容量大时 for(Map.Entry System.out.println(“key= ” + entry.getKey()+ “ and value= ” + entry.getValue()); } //第四种:通过Map.values()遍历所有的value,但不能遍历key for(Integer v : hashMap.values()){ System.out.println(“value= ” + v); } } } Map实现类LinkedHashMap LinkedHashMap继承自HashMap,它主要是用链表实现来扩展HashMap类,HshMap中条目是没有顺序的,但是在LinkedHashMap中元素既可以按照它们插入图的顺序排序,也可以按它们最后一次被访问 的顺序排序。LinkedHashMap继承自HashMap并且实现了Map接口。和HashMap一样,LinkedHashMap 允许key和value均为null。于该数据结构和HashMap一样使用到hash算法,因此它不能保证映射的顺序,尤其是不能保证顺序持久不变(再哈希)。 [html] view plain copy public class LinkedHashMapTest { public static void main(String[] args){ Map linkedHashMap.put(“a”, 1); linkedHashMap.put(“java”,2); linkedHashMap.put(“C”, 3); System.out.println(linkedHashMap.get(“a”)); Set Iterator while(iter.hasn(String[] args){ Map treeMap.put(“b”,2); treeMap.put(“a”,1); treeMap.put(“e”,5); treeMap.put(“d”,4); treeMap.put(“c”,3); Set Iterator while(iter.hasNext()){ System.out.println(iter.next()); } Set for(String x:keySet){ System.out.println(x+“=”+treeMap.get(x)); } Map treeMap2.put(new Num(2),“a”); treeMap2.put(new Num(1),“b”); treeMap2.put(new Num(5),“c”); treeMap2.put(new Num(4),“d”); treeMap2.put(new Num(3),“c”); Set for(Num x:keySet2){ System.out.println(x+“=”+treeMap2.get(x)); } //根据value排序 Map map.put(“d”, 2); map.put(“c”, 1); map.put(“b”, 4); map.put(“a”, 3); List new ArrayList //排序前 for(int i = 0;i < infoIds.size();i++){ String id = infoIds.get(i).toString(); System.out.println(id); } //排序 Collections.sort(infoIds, new Comparator public int compare(Map.Entry return(o2.getValue()-o1.getValue()); //return(o1.getKey()).toString().compareTo(o2.getKey()); } }); //排序后 for(int i = 0;i < infoIds.size();i++){ String id = infoIds.get(i).toString(); System.out.println(id); } } } Map接口总结:在实际使用中,如果更新图时不需要保持图中元素的顺序,就使用HashMap,如果需要保持图中元素的插入顺序或者访问顺序,就使用LinkedHashMap,如果需要使图按照键值排序,就使用TreeMap。 用编程的方式,我们可以要求(记住这只是一个请求――不是一个命令)JVM通过调用System.gc()方法来运行垃圾回收。 当内存已满,且堆上没有对象可用于垃圾回收时,JVM可能会抛出OutOfMemoryException。 对象在被垃圾回收从堆上删除之前,会运行finalize()方法。我们建议不要用finalize()方法写任何代码。 什么是初始化数据块? 初始化数据块――当创建对象或加载类时运行的代码。 有两种类型的初始化数据块: 静态初始化器:加载类时运行的的代码 实例初始化器:创建新对象时运行的代码 什么是静态初始化器? 请看下面的例子:static{和}之间的代码被称为静态初始化器。它只有在第一次加载类时运行。只有静态变量才可以在静态初始化器中进行访问。虽然创建了三个实例,但静态初始化器只运行一次。 public class InitializerExamples { static int count; int i; static{ //This is a static initializers. Run only when Class is first loaded. //Only static variables can be accessed System.out.println(“Static Initializer”); //i = 6;//COMPILER ERROR System.out.println(“Count when Static Initializer is run is ” + count); } public static void main(String[] args) { InitializerExamples example = new InitializerExamples(); InitializerExamples example2 = new InitializerExamples(); InitializerExamples example3 = new InitializerExamples(); } } 示例输出 Static Initializer Count whenStaticInitializer is run is0. 什么是实例初始化块? 让我们来看一个例子:每次创建类的实例时,实例初始化器中的代码都会运行。 public class InitializerExamples { static int count; int i; { //This is an instance initializers. Run every time an object is created. //static and instance variables can be accessed System.out.println(“Instance Initializer”); i = 6; count = count + 1; System.out.println(“Count when Instance Initializer is run is ” + count); } public static void main(String[] args) { InitializerExamples example = new InitializerExamples(); InitializerExamples example1 = new InitializerExamples(); InitializerExamples example2 = new InitializerExamples(); } } 示例输出 Instance Initializer Count when Instance Initializer is run is 1 Instance Initializer Count when Instance Initializer is run is 2 Instance Initializer Count when Instance Initializer is run is 3 什么是正则表达式? 正则表达式能让解析、扫描和分割字符串变得非常容易。Java中常用的正则表达式――Patter,Matcher和Scanner类。 什么是令牌化? 令牌化是指在分隔符的基础上将一个字符串分割为若干个子字符串。例如,分隔符;分割字符串ac;bd;def;e为四个子字符串ac,bd,def和e。 分隔符自身也可以是一个常见正则表达式。 String.split(regex)函数将regex作为参数。 给出令牌化的例子? private static void tokenize(String string,String regex) { String[] tokens = string.split(regex); System.out.println(Arrays.toString(tokens)); } tokenize(“ac;bd;def;e”,“;”);//[ac, bd, def, e] 如何使用扫描器类(Scanner Class)令牌化? private static void tokenizeUsingScanner(String string,String regex) { Scanner scanner = new Scanner(string); scanner.useDelimiter(regex); List matches = new ArrayList(); while(scanner.hasNext()){ matches.add(scanner.next()); } System.out.println(matches); } tokenizeUsingScanner(“ac;bd;def;e”,“;”);//[ac, bd, def, e] 如何添加小时(hour)到一个日期对象(Date Objects)? 现在,让我们如何看看添加小时到一个date对象。所有在date上的日期操作都需要通过添加毫秒到date才能完成。例如,如果我们想增加6个小时,那么我们需要将6小时换算成毫秒。6小时= 6 * 60 * 60 * 1000毫秒。请看以下的例子。 Date date = new Date(); //Increase time by 6 hrs date.setTime(date.getTime() + 6 * 60 * 60 * 1000); System.out.println(date); //Decrease time by 6 hrs date = new Date(); date.setTime(date.getTime() - 6 * 60 * 60 * 1000); System.out.println(date); 如何格式化日期对象? 格式化日期需要使用DateFormat类完成。让我们看几个例子。 //Formatting Dates System.out.println(DateFormat.getInstance().format( date));//10/16/12 5:18 AM 下一页123456 摘要 J2EE应用程序中的业务组件通常使用JDBC API访问和更改关系数据库中的持久数据。这经常导致持久性代码与业务逻辑发生混合,这是一种不好的习惯。数据访问对象(DAO)设计模式通过把持久性逻辑分成若干数据访问类来解决这一问题。 本文是一篇关于DAO设计模式的入门文章,突出讲述了它的优点和不足之处。另外,本文还介绍了Spring 2.0 JDBC/DAO框架并示范了它如何妥善地解决传统DAO设计中的缺陷。 传统的DAO设计 数据访问对象(DAO)是一个集成层设计模式,如Core J2EE Design Pattern 图书所归纳。它将持久性存储访问和操作代码封装到一个单独的层中。本文的上下文中所提到的持久存储器是一个RDBMS. 这一模式在业务逻辑层和持久存储层之间引入了一个抽象层,如图1所示。业务对象通过数据访问对象来访问RDBMS(数据源)。抽象层改善了应用程序代码并引入了灵活性。理论上,当数据源改变时,比如更换数据库供应商或是数据库的类型时,仅需改变数据访问对象,从而把对业务对象的影响降到最低。 图1. 应用程序结构,包括DAO之前和之后的部分 讲解了DAO设计模式的基础知识,下面将编写一些代码。下面的例子来自于一个公司域模型。简而言之,这家公司有几位员工工作在不同的部门,如销售部、市场部以及人力资源部。为了简单起见,我们将集中讨论一个称作“雇员”的实体。 针对接口编程 DAO设计模式带来的灵活性首先要归功于一个对象设计的最佳实践:针对接口编程(P2I)。这一原则规定实体必须实现一个供调用程序而不是实体自身使用的接口。因此,可以轻松替换成不同的实现而对客户端代码只产生很小的影响。 我们将据此使用findBySalaryRange行为定义Employee DAO接口,IEmployeeDAO.业务组件将通过这个接口与DAO交互: clearcase/“ target=”_blank“ >cccccc border=0 heihgt=”“> importjava.util.Map; public interface IEmployeeDAO { //SQL String that will be executed public String FIND_BY_SAL_RNG = ”SELECT EMP_NO, EMP_NAME, “ + ”SALARY FROM EMP WHERE SALARY >= ? AND SALARY <= ?“; //Returns the list of employees who fall into the given salary //range. The input parameter is the immutable map object //obtained from the HttpServletRequest. This is an early //refactoring based on ”Introduce Parameter Object“ public List findBySalaryRange(Map salaryMap); } 提供DAO实现类 接口已经定义,现在必须提供Employee DAO的具体实现,EmployeeDAOImpl: import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.List; import java.util.ArrayList; import java.util.Map; import com.bea.dev2dev.to.EmployeeTO; public class EmployeeDAOImpl implements IEmployeeDAO{ public List findBySalaryRange(Map salaryMap) { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; List empList = new ArrayList; //Transfer Object for inter-tier data transfer EmployeeTO tempEmpTO = null; try{ //DBUtil - helper classes that retrieve connection from pool conn = DBUtil.getConnection(); pstmt = conn.prepareStatement(FIND_BY_SAL_RNG); pstmt.setDouble(1, Double.valueOf( (String) salaryMap.get(”MIN_SALARY“) ); pstmt.setDouble(2, Double.valueOf( (String) salaryMap.get(”MIN_SALARY“) ); rs = pstmt.executeQuery(); int tmpEmpNo = 0; String tmpEmpName = ”“; double tmpSalary = 0.0D; while (rs.next()){ tmpEmpNo = rs.getInt(”EMP_NO“); tmpEmpName = rs.getString(”EMP_NAME“); tmpSalary = rs.getDouble(”SALARY"); tempEmpTO = new EmployeeTO(tmpEmpNo, tmpEmpName, tmpSalary); empList.add(tempEmpTO); }//end while }//end try catch (SQLException sqle){ throw new DBException(sqle); }//end catch finally{ try{ if (rs != null){ rs.close(); } } catch (SQLException sqle){ throw new DBException(sqle); } try{ if (pstmt != null){ pstmt.close(); } } catch (SQLException sqle){ throw new DBException(sqle); } try{ if (conn != null){ conn.close(); } } catch (SQLException sqle){ throw new DBException(sqle); } }//end of finally block return empList; }//end method findBySalaryRange } 【【java总结】集合框架】推荐阅读: java集合总结07-17 读书活动总结模板集合05-14 公司年会活动总结集合08-11 集合与集合的运算教案07-24 集合函数10-16 集合运算06-22 集合理论08-04 集合概念08-08 集合信托08-20 集合融资09-02高级Java面试题集合 篇2
【java总结】集合框架 篇3