遍历ArrayList
public class Test{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("HAHAHAHA");
//第一种遍历方法使用 For-Each 遍历 List
for (String str : list) { //也可以改写 for(int i=0;i<list.size();i++) 这种形式
System.out.println(str);
}
//第二种遍历,把链表变为数组相关的内容进行遍历
String[] strArray=new String[list.size()];
list.toArray(strArray);
for(int i=0;i<strArray.length;i++) //这里也可以改写为 for(String str:strArray) 这种形式
{
System.out.println(strArray[i]);
}
//第三种遍历 使用迭代器进行相关遍历
Iterator<String> ite=list.iterator();
while(ite.hasNext())//判断下一个元素之后有值
{
System.out.println(ite.next());
}
}
}
遍历Map
public class Test{
public static void main(String[] args) {
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和value:");
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
//第二种
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.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.values()遍历所有的value,但不能遍历key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
}
}
删除链表中的元素:
LinkedList<String> lList = new LinkedList<String>();
lList.add("1");
lList.add("8");
lList.add("6");
lList.add("4");
lList.add("5");
System.out.println(lList);
lList.subList(2, 4).clear();
System.out.println(lList);
类型通配符:
类型通配符一般是使用?代替具体的类型参数。例如 List<?> 在逻辑上是List<String>,List<Integer>
等所有List<具体类型实参>的父类
public class GenericTest {
public static void main(String[] args) {
List<String> name = new ArrayList<String>();
List<Integer> age = new ArrayList<Integer>();
List<Number> number = new ArrayList<Number>();
name.add("icon");
age.add(18);
number.add(314);
getData(name);
getData(age);
getData(number);
}
public static void getData(List<?> data) {
System.out.println("data :" + data.get(0));
}
}
Java的集合对象可以调用toArray()方法将集合中所有数据提取到一个新的数组中:
public<T>T[] toArray(T[] array);
array:保存集合数据的数组
ArrayList提供了一个将List转为数组的一个非常方便的方法toArray。toArray有两个重载的方法:
(1)list.toArray();//将list直接转为Object[]数组
(2)list.toArray(T[] a);
HashMap存储过程:
当程序执行map.put(“语文”,80)时。系统将调用"语文"的hashCode()方法得到其hashCode(每个java对象都有hashCode()方法),然后根据hashCode值决定该元素的存储位置
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);//搜索指定hash值在对应table中的索引
其实每个Map.Entry就是一个key-value对,如果两个Entry的key的通过equals比较返回true,则value将覆盖原有Entry的value,如果返回false,则新添加的Entry将与集合中原有Entry形成Entry链当程序执行map.get(“key”)时,系统通过key的hashCode()返回值找出key在table数组中的索引,然后取出该索引处的Entry,最后返回对应的value
总结:
HashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象,HashMap底层采用一个Entry[]数组来保存所有的key-value对,根据Hash算法来决定其存储位置
HashSet:
HashSet是基于HashMap实现的,HashSet底层封装了一个HashMap对象来保存所有集合元素,所有放入HashSet中的集合元素实际上由HashMap的key来保存,而HashMap的value则存储了一个静态Object对象,因此HashMap和HashSet在实现本质上是相同的。
将某个类的对象放入HashSet中保存时,需要重写该类的equals(Object obj)和hashCode()方法,而且这两个方法的返回值必须保持一致
例如果重写类的hashCode()和equals():
class Name{
private String first;
private String last;
public Name(String first,String last){
this.first = first;
this.last = last;
}
//根据first判断2个Name是否相等
public boolean equals(Object o){
if(this == 0){
return true;
}
if(o.getClass() == Name.class){
Name n = (Name)o;
return n.first.equals(first);
}
return false;
}
//根据first计算Name对象的hashCode()返回值
public int hashCode(){
return first.hashCode();
}
}
public class HashSetTest{
public static void main(String[] args)
{
HashSet<Name> set = new HashSet<Name>();
set.add(new Name("abc","123"));
set.add(new Name("abc","456"));
System.out.println(set);
}
}
TreeSet底层也是使用TreeMap来包含Set集合:
对于TreeMap而言,它采用一种被称为“红黑树”的排序二叉树来保存Map中的每个Entry—每个Entry都被当成“红黑树”的一个节点对待,保证了TreeMap中所有key总是由小到大地排列;因此TreeMap添加元素和取出元素的性能都比HashMap低,而且是有序排序。
红黑树是一种自平衡二叉查找树,数中每个节点的值都大于或等于在它的左子树中的所有节点的值,并且小于或等于在它的右子树中的所有节点的值
总结:不管是HashMap还是TreeMap,它们的values()方法都可返回其所有value组成的Collection集合,也就是个List集合,实际上就是遍历Map对象的value
Vector为什么是线程安全的类:
Vector有一个Stack子类,并增加了几个方法,这些方法使用了synchronized修饰
ArrayList和LinkedList:
List代表一种线性表的数据结构,ArrayList则是一种顺序存储的线性表。ArrayList底层采用数组来保存每个集合元素,LinkedList则是一种链式存储的线性表,其本质就是一个双向链表,因为它实现了List接口和Deque接口;
区别:
LinkedList在添加集合元素时只要对链表在指定节点之前添加一个新节点就行,对于ArrayList而言,由于底层采用数组来保存集合元素,因此可以直接根据数组索引取出index位置的元素,但LinkedList必须一个个元素地搜索,直到找到第index个元素为止。
迭代器模式:
对于Iterator迭代器而言,它只是个接口,Java要求各种集合都提供一个iterator()方法,该方法可以返回一个Iterator用于遍历该集合中元素,至于返回的Iterator到底是哪种实现类程序并不关心。