java集合主要包括以下几点
- Java 集合概述
- Collection 接口
- Iterator 接口
- Set
- List
- Map
- Collections 工具类
- Enumeration
1.java集合概述
2.Collection 接口,Iterator接口
public class TestCollection { public static void main(String[] args) { //1. 创建一个 Collection 接口的对象。接口对象,使用多态的方式. Collection collection = new ArrayList(); //2. Collection 重要方法说明: /** * 2.1 用于添加元素的: * add():加入一个对象 * addAll():加入一组对象 */ Person p1 = new Person(); collection.add(p1); collection.add(new Person()); Collection collection2 = new ArrayList(); collection2.add(new Person()); collection2.add(new Person()); collection.addAll(collection2); System.out.println(collection.size()); /** * 2.2 用于访问集合的方法: * size():获取集合的长度: * iterator():对集合进行遍历的方法,可以得到对应的 Iterator 接口对象. * * Iterator: 迭代器 * ①. 获取 Iterator 接口对象: * ②. 使用 while 循环和 Iterator 对象遍历集合中的每一个元素. 具体使用 Iterator 接口的 * hasNext() 和 next() 方法. */ Iterator iterator = collection.iterator(); while(iterator.hasNext()){ Object obj = iterator.next(); System.out.println(obj); } /** * 2.3 移除集合中的元素: * remove(): 移除某一个指定的对象. (API中)通过调用对象的 equals() 方法来判断要移除的那个元素在集合中是否存在. 以及是否能够成功移除. * 也就是说拿当前对象和集合中的对象一个个的比,如果有相同的equal返回true,就可以移除掉 * 但是如果在Person里面重写了equals()方法,而且始终返回false,那么就永远也无法移出一个Person对象 * removeAll():移出一组对象 * clear(): 使集合中的元素置空. */ collection.clear(); boolean result = collection.remove(p1); System.out.println(result); result = collection.removeAll(collection2); System.out.println(collection.size()); /** * 2.4 用于检测集合的方法 * retains():是否包含一个对象 * retainsAll():是否包含一个对象集合 * isEmpty() * */ System.out.println(collection.contains(new Person()));//false System.out.println(collection.contains(p1));//true System.out.println(collection.containsAll(collection2));//true System.out.println(collection.isEmpty()); //false collection.clear(); System.out.println(collection.isEmpty()); //true /** * 2.5 其他方法 * toArray(): 返回集合对应的数组对象 * T [] toArray(T[]): 涉及到泛型(比如传入参数是一个Person对象数组,那么返回值也是一个Person对象数组) * * equals(): 比较两个集合是否相等. * 如果是ArrayList,不仅长度和每个对象都要一样,而且顺序也要一样,因为ArrayList是有顺序的 * 对于HashSet就没有顺序要求 * hasCode(): 返回集合的哈希码 */ Object [] objs = collection.toArray(); System.out.println(objs.length); //4 Person p2 = new Person(); Collection collection3 = new HashSet(); collection3.add(p1); collection3.add(p2); Collection collection4 = new HashSet(); collection4.add(p2); collection4.add(p1); System.out.println(collection3.equals(collection4)); /** * 使用增强 for 循环的方式来对集合进行遍历 */ for(Object obj: collection){ System.out.println(obj); } } }
3.Set
Set接口是Collection的子接口,所以前面讲的方法都可以用
Set中包含
public static void main(String[] args) { Set set = new HashSet(); //可以存放null set.add(null); System.out.println(set.size()); //1 //存放同一个对象 Person p1 = new Person(); set.add(p1); set.add(p1); System.out.println(set.size()); //2 //存放两个对象,当对象各个属性相同时,也要只存一次 //这种情况必须重写待存入类Person类的hashCode和equals方法 set.add(new Person("AA", 12)); set.add(new Person("AA", 12)); System.out.println(set.size()); //3 //输出结果是不按顺序的 set.add(new Person("FF", 13)); Iterator it = set.iterator(); while(it.hasNext()){ System.out.println(it.next()); } }
1 public class Person { 2 private String name; 3 private int age; 4 5 public Person(String name, int age) { 6 super(); 7 this.name = name; 8 this.age = age; 9 } 10 public Person() { 11 super(); 12 } 13 @Override 14 public int hashCode() { 15 final int prime = 31; 16 int result = 1; 17 result = prime * result + age; 18 result = prime * result + ((name == null) ? 0 : name.hashCode()); 19 return result; 20 } 21 @Override 22 public boolean equals(Object obj) { 23 if (this == obj) 24 return true; 25 if (obj == null) 26 return false; 27 if (getClass() != obj.getClass()) 28 return false; 29 Person other = (Person) obj; 30 if (age != other.age) 31 return false; 32 if (name == null) { 33 if (other.name != null) 34 return false; 35 } else if (!name.equals(other.name)) 36 return false; 37 return true; 38 } 39 }
Set的add方法时,调用了equals方法,查看是否有返回值为true的对象。同样,add方法同时也调用了hashCode,根据方法的返回的该对象的hashCode值来决定该对象的存储位置。
默认情况下,如果两个对象equals的返回值是true,那么对应的hashCode值一定相等。所以存储的位置是一样的,只能存一次。
//根据对象的属性生成一个hashCode值 //但是如果属性各个不相等,那么最后加起来可能就相等了 //这里定义了prime这个素数来解决这个问题 @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; }
我们把它改成:
private static int init = 0;
@Override public int hashCode() { return init++; }
这样任何两个对象的hashCode都不会再相等了。hashSet将会把它们存储在不同的位置,依然可以添加成功(正常开发中不会出现这种情况)。
3.2 LinkedHashSet
public static void main(String[] args) { Set set = new LinkedHashSet(); set.add(null); Person p1 = new Person(); set.add(p1); set.add(p1); set.add(new Person("AA", 12)); set.add(new Person("AA", 12)); set.add(new Person("FF", 13)); Iterator it = set.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } //返回结果是 返回结果的顺序就是插入的顺序 // null // com.atguigu.java.Person@3c1 // com.atguigu.java.Person@d55 // com.atguigu.java.Person@e14
3.3 TreeSet
1 public class Person implements Comparable{ 2 private String name; 3 private int age; 4 5 public Person(String name, int age) { 6 super(); 7 this.name = name; 8 this.age = age; 9 } 10 public Person() { 11 super(); 12 } 13 14 15 @Override 16 public int hashCode() { 17 final int prime = 31; 18 int result = 1; 19 result = prime * result + age; 20 result = prime * result + ((name == null) ? 0 : name.hashCode()); 21 return result; 22 } 23 @Override 24 public boolean equals(Object obj) { 25 if (this == obj) 26 return true; 27 if (obj == null) 28 return false; 29 if (getClass() != obj.getClass()) 30 return false; 31 Person other = (Person) obj; 32 if (age != other.age) 33 return false; 34 if (name == null) { 35 if (other.name != null) 36 return false; 37 } else if (!name.equals(other.name)) 38 return false; 39 return true; 40 } 41 @Override 42 public int compareTo(Object o) { 43 if(o instanceof Person){ 44 Person stu = (Person) o; 45 return this.age - stu.age; 46 }else{ 47 throw new ClassCastException("不是一个Student对象. "); 48 } 49 } 50 @Override 51 public String toString() { 52 return "Person [name=" + name + ", age=" + age + "]"; 53 } 54 }
那么进行排序输出:
public static void main(String[] args) { Set set = new TreeSet(); set.add(new Person("AA", 98)); set.add(new Person("BB", 50)); set.add(new Person("CC", 95)); System.out.println(set.size()); for(Object obj: set){ System.out.println(obj); } } //f返回值是: // 3 // Person [name=BB, age=50] // Person [name=CC, age=95] // Person [name=AA, age=98]
默认是升序排序,如何倒序呢?
//倒序:返回比较结果的相反数 @Override public int compareTo(Object o) { if(o instanceof Person){ Person stu = (Person) o; return -(this.age - stu.age); }else{ throw new ClassCastException("不是一个Person对象. "); } }
如何根据name字段进行排序呢?
//name排序:字符串已经实现了Compareable接口 @Override public int compareTo(Object o) { if(o instanceof Person){ Person stu = (Person) o; return this.name.compareTo(stu.name); }else{ throw new ClassCastException("不是一个Person对象. "); } }
如果equals方法和comparableTo方法的返回值不一样,会出现怎么样的结果?
public static void main(String[] args) { Set set = new TreeSet(); set.add(new Person("AA", 98)); set.add(new Person("BB", 90)); set.add(new Person("CC", 95)); set.add(new Person("DD", 98)); System.out.println(set.size()); for(Object obj: set){ System.out.println(obj); } } //返回值是: // 3 // Person [name=BB, age=90] // Person [name=CC, age=95] // Person [name=AA, age=98]
插入了四个对象,为什么才有三个成功呢?Person类里是重写了equals方法,而且实现了Comparable 接口 compareTo(Object obj) 方法,并按age字段排序。
当在添加元素时,从Set的角度,四个对象equals方法返回的值都不一样,都应该添加,但是从TreeSet的角度,它是排序添加,添加时第一个对象和第四个对象compareTo返回的值是相等的所以又不能添加了。
2.定制排序
/** * 定制排序: 创建 TreeSet 对象时, 传入 Comparator 接口的实现类. * 要求: Comparator 接口的 compare 方法的返回值和 两个元素的 equals() 方法具有一致的返回值 * @param args */ public static void main(String[] args) { //创建一个内部类 Comparator comparator = new Comparator() { @Override public int compare(Object o1, Object o2) { if(o1 instanceof Person && o2 instanceof Person){ Person p1 = (Person) o1; Person p2 = (Person) o2; return p1.getAge() - p2.getAge(); }else{ throw new ClassCastException("不能转为 Person"); } } }; Set set2 = new TreeSet<>(comparator); set2.add(new Person("BB", 12)); set2.add(new Person("CC", 16)); set2.add(new Person("DD", 15)); for(Object obj: set2){ System.out.println(obj); } } //f返回值是: // 3 // Person [name=BB, age=12] // Person [name=CC, age=15] // Person [name=AA, age=16]
4. List
http://www.cnblogs.com/tech-bird/p/3635032.html
4.1 ArrayList
ArrayList遍历的三种方式
public static void main(String[] args) { List list = new ArrayList(); list.add(new Person("AA", 12)); list.add(new Person("BB", 13)); list.add(new Person("CC", 14)); list.add(new Person("DD", 15)); //对 list 进行遍历 Iterator it = list.iterator(); while(it.hasNext()){ System.out.println(it.next()); } //使用 for 循环的方式对 list 进行遍历: 增强的 for 循环 for(Object obj: list){ System.out.println(obj); } //使用 for 循环的方式对 list 进行遍历: 使用 List 的 get(int) 方法 for(int i = 0; i < list.size(); i++){ System.out.println(list.get(i)); } //使用ListIterator进行遍历(hasNext()和hasPrevious向后和向前) ListIterator lit = list.listIterator(); while(lit.hasNext()){ System.out.println(lit.next()); } }
indexOf方法:获取一个元素在集合中的位置。那么首先得知道这个元素在集合中存在不存在,靠的是equals方法。
public static void main(String[] args) { List list = new ArrayList(); list.add(new Person("AA", 12)); list.add(new Person("BB", 13)); list.add(new Person("CC", 14)); list.add(new Person("DD", 15)); System.out.println(list.indexOf(new Person("BB", 13))); }
同前面讲的一样,必须让Person类重写equals方法,才能返回1,否则返回 -1
其他方法:
public static void main(String[] args) { List list = new ArrayList(); list.add(new Person("AA", 12)); list.add(new Person("BB", 13)); list.add(new Person("CC", 14)); list.add(new Person("DD", 15)); //把一个元素放到指定的位置 list.add(2, new Person("EE", 16)); //把一个元素加到末尾 list.add(new Person("EE", 16)); //获取指定元素在集合中的第一个位置 System.out.println(list.indexOf(new Person("EE", 16))); //2 //获取指定元素在集合中的最后一个位置 System.out.println(list.lastIndexOf(new Person("EE", 16))); //5 //相当于rePlace,把元素替换指定位置的元素 list.set(3, new Person("AA", 12)); //获取一个指定区间的集合(半闭半开区间) List list2 = list.subList(2, 5); //2, 3, 4 }
public static void main(String[] args) { System.out.println(Arrays.asList(new Person("MM", 23), new Person("NN", 24))); } } //f返回值是: // [Person [name=MM, age=23], Person [name=NN, age=24]]
集合和数组之间的转化:
1. public static <T> List<T> asList(T... a)
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
2. Object[] toArray() 或者 <T> T[] toArray(T[] a)
5.Map
public interface Map<K,V> { //..... }
Map接口的方法:
public static void main(String[] args) { //Map接口的典型实现是HashMap Map map = new HashMap(); //1. 向 Map 中添加元素的: // put(key, value); 放入一个指定的键值对 // put(map) 放入一组键值对 map.put("AA", new Person("AA", 12)); map.put("AA", new Person("AAA", 12)); //key值重复,会把上一个覆盖 map.put("CC", new Person("CCC", 12)); map.put("MM", new Person("MMM", 12)); map.put("II", new Person("AAA", 12)); //2. 从 Map 中取出元素的(遍历) //2.1 得到键的集合: keySet(). Set keySet = map.keySet(); //用Set,不可重复 for(Object key: keySet){ //利用键得到值: get(key) Object value = map.get(key); System.out.println(key + ": " + value); } //2.2 直接得到 value 的集合 Collection values = map.values(); //用Collection,可以重复 System.out.println(values.getClass()); for(Object val: values){ System.out.println(val); } //2.3 得到 键值对的 集合(泛型) // 首先要把前面Map对象的定义改成 Map<String,Object> map = new HashMap<>(); for(Map.Entry<String, Object> entry: map.entrySet()){ String key = entry.getKey(); Object val = entry.getValue(); System.out.println(key + ": " + val); } //3. 移除元素的 map.remove("AA"); //4. 工具方法: //4.1 size() 方法 System.out.println(map.size()); System.out.println(map); //4.2 contains(); isEmpty() System.out.println(map.containsKey("BB")); System.out.println(map.isEmpty()); }
HashMap和HashSet的关系
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { static final long serialVersionUID = -5024744406713321676L; private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); public Iterator<E> iterator() { return map.keySet().iterator(); } public int size() { return map.size(); } public boolean isEmpty() { return map.isEmpty(); } public boolean contains(Object o) { return map.containsKey(o); } //............ }
可以看出,在HashSet里面维护了一个HashMap对象,其中的Key值就是HashSet里的元素(无序,不重复),Value值是一个Object类型的常量。所以对HashSet的操作都是通过调用HashMap来实现的。
所以HashMap与HashSet相似之处
- Key值无序,不重复
- HashMap 可以使用 null 作为 key 和 value
- HashMap 判断两个 Key 相等的标准是:两个 Key 通过 equals 方法返回 true,hashCode 值也相等。
- HashMap 判断两个 Value相等的标准是:两个 Value 通过 equals 方法返回 true
5.2 HashTable
5.3 LinkedHashMap
public LinkedHashSet() { super(16, .75f, true); } HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); }
public TreeSet() { this(new TreeMap<E,Object>()); }
比如:
public static void main(String[] args) { Comparator comparator = new Comparator() { @Override public int compare(Object o1, Object o2) { Person p1 = (Person) o1; Person p2 = (Person) o2; return p1.getAge() - p2.getAge(); } }; TreeMap tm = new TreeMap(comparator); tm.put(new Person("AA", 12), "AAA"); tm.put(new Person("BB", 22), "AAA"); tm.put(new Person("CC", 2), "AAA"); tm.put(new Person("DD", 9), "AAA"); Set keySet = tm.keySet(); for(Object key: keySet){ Object val = tm.get(key); System.out.println(key + ": " + val); } } } //返回值是: // // Person [name=CC, age=2]: AAA // Person [name=DD, age=9]: AAA // Person [name=AA, age=12]: AAA // Person [name=BB, age=22]: AAA
5.5 Properties
属性(Properties)文件在Java 中对一个的是一个 Properties 类的对象
如何加载一个属性文件:
首先要new一个File,命名为 jdbc.properties,内容为:
url=jdbc:mysql:///test driver=com.mysql.jdbc.Driver user=root password=1230
获取信息:
public static void main(String[] args) throws Exception { /** * properties 文件在 Java 中对一个的是一个 Properties 类的对象 */ //1. 创建一个 Properties 类的对象 Properties properties = new Properties(); //2. 使用 IO 流加载对应的 properties 文件 // 文件一定要和src同目录,否则要写全路径 properties.load(new FileInputStream("jdbc.properties")); //3. 得到对应的属性值(通过键来获取值) String url = properties.getProperty("url"); System.out.println(url); }
6.Collections 工具类
Collection是一个接口,而Collections 是一个操作 Set、List 和 Map 等集合的工具类(含有的工具方法全部都是静态方法)
static <T extends Object & Comparable<? super T>> T | min(Collection<? extends T> coll)
Returns the minimum element of the given collection, according to the natural ordering of its elements.
|
static <T> T | min(Collection<? extends T> coll, Comparator<? super T> comp)
Returns the minimum element of the given collection, according to the order induced by the specified comparator.
|
又比如这两个方法,都是获取集合中最小的元素,第一个方法要求 集合中的元素必须要实现Comparable接口,第二个要求集合本身实现了Comparator(利用内部类)
对List进行排序
public static void main(String[] args) throws Exception { List list = new ArrayList(); list.add(new Person("AA", 12)); list.add(new Person("BB", 11)); list.add(new Person("CC", 5)); list.add(new Person("DD", 10)); //使用 Collections 中的方法对 List 中的元素进行排序 Collections.sort(list, new Comparator() { @Override public int compare(Object o1, Object o2) { Person p1 = (Person) o1; Person p2 = (Person) o2; return - p1.getAge() + p2.getAge(); } }); for(Object obj: list){ System.out.println(obj); } }
同步控制方法:
前面说ArrayList是线程不安全的,那么可以把它变成安全的
List list = Collections.synchronizedList(new ArrayList<>());
这样得到的list对象就是线程安全的。(只要传入一个集合,出来的集合就是线程安全的)
同理,Set,Map,Collection都有类似的方法
//获取线程安全的 List 对象, 使用 synchronizedList() List list2 = Collections.synchronizedList(new ArrayList<>());
当我们操作集合的时候,如果觉得需要什么方法,都可以到Collections 类中来找
7 .Enumeration
//对 Enumeration 对象进行遍历: hasMoreElements() nextElement() Enumeration names = Collections.enumeration(list); while(names.hasMoreElements()){ Object obj = names.nextElement(); System.out.println(obj); }
使用的时候,不会创建一个Enumeration对象,而是根据一些API得到Enumeration对象,然后进行遍历