线程安全
在Java里,线程安全一般体现在两个方面:
1、多个thread对同一个java实例的访问(read和modify)不会相互干扰,它主要体现在关键字synchronized.如ArrayList和Vector,HashMap和Hashtable(后者每个方法前都有synchronized关键字)。如果你在interator一个List对象时,其它线程remove一个element,问题就出现了。
2、每个线程都有自己的字段,而不会在多个线程之间共享。它主要体现在java.lang.ThreadLocal类,而没有Java关键字支持,如像static、transient那样。
1、得到list里的数据
@Test public void testGetData() { List<String> list = new ArrayList<String>(); list.add("aa"); list.add("bb"); list.add("cc"); //1、通过下标得到数据 System.out.println(list.get(0)); //2、通过for循环得到数据,最常用 for (String str : list) { System.out.println(str); } //3、通过iterator,不建议使用 Iterator<String> it = list.iterator(); while (it.hasNext()){ System.out.println(it.next()); } }
@Test public void subList() { ArrayList<Integer> originalList = new ArrayList<Integer>(); for (int i = 0; i < 5; i++) { originalList.add(i); // auto boxing } // 一开始的list数据 System.out.print("the original list: "); for (Integer num : originalList) { System.out.print(num + " "); // 0 1 2 3 4 } System.out.println(); // 用subList后的list 1 2 3!!! List<Integer> subList = originalList.subList(1, 4); // 移除2 subList.remove(1); System.out.print("sub list: "); for (Integer num : subList) { System.out.print(num + " "); // 1 3 } System.out.println(); // 一开始的list数据 System.out.print("the original list after subList modified: "); for (Integer num : originalList) { System.out.print(num + " "); // 0 1 3 4 } }
3、list排序
先创建一个对象
public class User implements Comparable<User>{ private String name; private Integer order; private double money; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getOrder() { return order; } public void setOrder(Integer order) { this.order = order; } public double getMoney() { return money; } public void setMoney(double money) { this.money = money; } @Override public int compareTo(User user) { //比较的参数需是对象 return this.getOrder().compareTo(user.getOrder()); } // //降序 // @Override // public int compareTo(User user) { // if (user.getMoney() < this.getMoney()) { // return -1; // } else if (user.getMoney() == this.getMoney()) { // return 0; // } else { // return 1; // } // } }
@Test public void testSort1() { User user1 = new User(); user1.setName("a"); user1.setOrder(1); User user2 = new User(); user2.setName("b"); user2.setOrder(2); List<User> list = new ArrayList<User>(); list.add(user2); list.add(user1); Collections.sort(list); for (User u : list){ System.out.println("test1: "+u.getName());//输出结果如下a b } }2、第二种方法是根据Collections.sort重载方法来实现,类中就定义简单的属性就行,例如:
@Test public void testSort2() { User user1 = new User(); user1.setName("a"); user1.setOrder(1); User user2 = new User(); user2.setName("b"); user2.setOrder(2); List<User> list = new ArrayList<User>(); list.add(user2); list.add(user1); //根据order对User排序 Collections.sort(list, new Comparator<User>() { @Override public int compare(User o1, User o2) { return o1.getOrder().compareTo(o2.getOrder()); } }); for (User u : list){ System.out.println("test1: "+u.getName());//输出结果如下a b } }
map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等。其中这四者的区别如下(简单介绍):
HashMap:基于哈希表实现,它根据key的HashCode 值来存储数据,根据key可以直接获取它的Value,同时它具有很快的访问速度。HashMap最多只允许一条记录的key值为Null(多条会覆盖);允许多条记录的Value为 Null。非同步的(非线程安全)。
TreeMap: 基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。能够把它保存的记录根据key排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的(非线程安全)。
Hashtable: 与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。
LinkedHashMap: 保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的(非线程安全)。
@Test public void testMap() { System.out.println("*************************HashMap*************"); Map<String, String> hashMap = new HashMap<String, String>(); hashMap.put("d", "apple"); hashMap.put("a", "banana"); hashMap.put("c", "pear"); hashMap.put("b", "orange"); for (String key : hashMap.keySet()) { System.out.println(key + "=" + hashMap.get(key)); //d=apple b=orange c=pear a=banana } System.out.println("*************************Hashtable*************"); //hashTable: 与 HashMap类似,不同的是:key和value的值均不允许为null Map<String, String> hashTable = new Hashtable<String, String>(); hashTable.put("d", "apple"); hashTable.put("a", "banana"); hashTable.put("c", "pear"); hashTable.put("b", "orange"); for (String key : hashTable.keySet()) { System.out.println(key + "=" + hashTable.get(key)); //b=orange a=banana d=apple c=pea } System.out.println("*************************LinkedHashMap*************"); //LinkedHashMap是HashMap的一个子类,它保留插入的顺序 Map<String, String> linkedHashMap = new LinkedHashMap<String, String>(); linkedHashMap.put("d", "apple"); linkedHashMap.put("a", "banana"); linkedHashMap.put("c", "pear"); linkedHashMap.put("b", "orange"); for (String key : linkedHashMap.keySet()) { System.out.println(key + "=" + linkedHashMap.get(key)); //按顺序输出d=apple a=banana c=pear b=orange } System.out.println("*************************TreeMap*************"); //TreeMap: 根据key排序,默认是按升序排序 Map<String, String> treeMap = new TreeMap<String, String>(); treeMap.put("d", "apple"); treeMap.put("a", "banana"); treeMap.put("c", "pear"); treeMap.put("b", "orange"); for (String key : treeMap.keySet()) { System.out.println(key + "=" + treeMap.get(key)); //a=banana b=orange c=pear d=apple } }
map有三种可能的视图
所有 键值对 | 参见 entrySet() | 返回 Map 中所包含映射的 Set 视图。 Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素 |
所有键 | 参见 keySet() | 返回 Map 中所包含键的 Set 视图。 删除 Set 中的元素还将删除 Map 中相应的映射(键和值) |
所有值 | 参见 values() | 返回 map 中所包含值的 Collection 视图。 删除 Collection 中的元素还将删除 Map 中相应的映射(键和值) |
@Test public void testTraverseMap() { Map<String, String> map = new HashMap<String, String>(); map.put("1", "value1"); map.put("2", "value2"); map.put("3", "value3"); //第一种:普遍使用,二次取值 System.out.println("通过Map.keySet遍历到的是key,通过key获取value: "); for (String key : map.keySet()) { System.out.println("key= " + key + " and value= " + map.get(key)); } //第二种:推荐,尤其是容量大时 System.out.println("通过Map.entrySet遍历key和value"); for (Map.Entry<String, String> entry : map.entrySet()) { System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue()); } //第三种 System.out.println("通过Map.entrySet使用iterator遍历key和value: "); Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, String> entry = it.next(); System.out.println("key= " + entry.getKey() + "and value= " + entry.getValue()); } //第四种 System.out.println("通过Map.values()遍历所有的value,但不能遍历key"); for (String v : map.values()) { System.out.println("value= " + v); } }
set集合不允许包含相同的元素(唯一性);判断两个对象是否相同是根据equals()方法,而不是==,返回true
1、HashSet类不是同步的(不是线程安全的)
Java.util.HashSet类实现了Java.util.Set接口。
* l.1 它不允许出现重复元素;
* l.2 根据hashCode()值来存放元素,所以不保证集合中元素的排列顺序
* l.3 允许包含值为null的元素,但最多只能有一个null元素。
* 1.4.如果两个对象通过equals()方法返回true,这两个对象的hashCode值也相同
@Test public void testHashSet() { Set<java.io.Serializable> h = new HashSet<java.io.Serializable>(); h.add("1st"); h.add("2nd"); h.add(3); h.add(4.0); h.add("2nd"); //重复元素,未被添加 h.add(3); //重复元素,未被添加 h.add(new Date()); System.out.println("开始:size=" + h.size());//5 for (Serializable o : h) { System.out.println(o); //2nd 3 1st 4.0 时间 } h.remove("2nd"); System.out.println("移除元素后:size=" + h.size()); // System.out.println(h); }2、TreeSet描述的是Set的一种变体——可以实现排序等功能的集合,
@Test public void testTreeSet() { Set<String> ts = new TreeSet<String>(); ts.add("orange"); ts.add("apple"); ts.add("banana"); ts.add("grape"); for (String fruit : ts) { System.out.print(fruit + " ");//apple banana grape orange } }