java知识点拾遗(容器)

  1. 常用容器

    其中Vector是线程安全的,而Collection线程不安全。线程安全的效率也低。

  2. 泛型
    数据类型的参数化。数据类型的一个占位符(形参)。告诉编译器,在调用泛型时必须传入实际类型。一般使用<T,E,V>三个字母。

  • 取消了强制类型转换
  • 编译期类型检查

泛型的上下界

  • 上界
    谁(?)是Person的子类(extends),谁就可以使用该泛型定义的方法。含Person。
public static void print(ArrayList<? extends Person> a1){
...
}
  • 下界
    谁(?)是Student的父类(super),谁就可以使用该泛型定义的方法。含Student。
public static void show(ArrayList<? super Student> a1){
......
}
  1. TreeMap的使用
    在有排序需求的时候使用。底层使用红黑树组织数据。
import java.util.Map;
import java.util.TreeMap;

public class Test1 {

	public static void main(String[] args) {

		Map<Integer, String> treemap1 = new TreeMap<>();
		treemap1.put(30, "张飞");
		treemap1.put(20, "吕布");
		treemap1.put(10, "关羽");

		// 按key递增的方式排序
		for (int key : treemap1.keySet()) {
			System.out.println(treemap1.get(key));
		}

		Map<Stuff, String> treemap2 = new TreeMap<>();
		treemap2.put(new Stuff(56, "赵云", 8000), "怀抱阿斗者");
		treemap2.put(new Stuff(31, "诸葛亮", 3000), "运筹帷幄");
		treemap2.put(new Stuff(10, "刘备", 5000), "中山晋王之后");
		treemap2.put(new Stuff(16, "孙夫人", 5000), "赔了夫人又折兵");

		// 按key递增的方式排序
		for (Stuff key : treemap2.keySet()) {
			System.out.println(key + " " + treemap2.get(key));
		}

	}
}

class Stuff implements Comparable<Stuff> {
	int id;
	String name;
	double salary;

	public Stuff(int id, String name, double salary) {
		this.id = id;
		this.name = name;
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "(id=" + id + ",name=" + name + ",salary=" + salary + ")";
	}

	@Override
	public int compareTo(Stuff o) {
		if (salary > o.salary) {
			return 1;
		} else if (salary < o.salary) {
			return -1;
		} else {
			if (id > o.id) {
				return 1;
			} else if (id < o.id) {
				return -1;
			} else {
				return 0;
			}
		}
	}
}

  1. HashMap与HashTable的区别
  • HashMap:线程不安全,效率高。允许key或者value为null。
  • HashTable :线程安全,效率低。不允许key或者value为null。
  1. Set接口
  • Set容器特点:无序、不可重复。无序指Set中的元素没有索引,我们只能遍历查找;不可重复指不允许加入重复的元素。更确切地讲,新元素如果和Set中某个元素通过equals()方法对比为true,则不能加入;甚至,Set中也只能放入一个null元素,不能多个。

  • HashSet底层也是由HashMap实现的。当然TreeSet底层也是由TreeMap实现的。

  • 注意:
    TreeMap是对key排序,而TreeSet是对元素排序。自定义对象的排序规则时,TreeMap是对key(对象)实现Comparable接口重写compareTo()方法;而TreeSet是对元素(对象)实现Comparable接口重写compareTo()方法。这里的Comparable接口是提供内部比较器的方式,还可以提供外部比较器——即实现Comparator接口重写compare()方法。其中字符串String的比较可以借助compareTo()方法。

  • 在HashSet中存放POJO:
    必须重写hashCode()方法及equals()方法。

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * HASH表的存储原理(存储为顺序表+链表。顺序表根据装填因子
     * (load_factor=loaded_element_no/list.length)调整扩容减少冲突
     * (load_factor>=0.75就扩容顺序表list),
     * 链表长度>=8后采用红黑树(一种平衡二叉树,优化查找次数)存储数据并优化查找。)
     * 1. 调用hashCode()计算HASH值
     * 2. 根据哈希函数计算存储位置
     * 3. 如果存储位置上没有元素则存储之
     * 4. 否则要调用equals()比较内容是否相同(冲突处理时调用)
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        System.out.println("调用hashCode():"+result);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            System.out.println("调用equals():true");
            return true;
        }
        if (obj == null) {
            System.out.println("调用equals():false");
            return false;
        }
        if (getClass() != obj.getClass()) {
            System.out.println("调用equals():false");
            return false;
        }
        Person other = (Person) obj;
        if (age != other.age) {
            System.out.println("调用equals():false");
            return false;
        }
        if (name == null) {
            if (other.name != null) {
                System.out.println("调用equals():false");
                return false;
            }
        } else if (!name.equals(other.name)) {
            System.out.println("调用equals():false");
            return false;
        }
        System.out.println("调用equals():true");
        return true;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试

public class Test01 {

    public static void main(String[] args) {
        Set<Person> hs=new HashSet<>();
        Person p1=new Person("林冲",31);
        Person p2=new Person("宋江",41);
        Person p3=new Person("林冲",31);
        Person p4=new Person("李逵",28);

        hs.add(p1);
        hs.add(p2);
        hs.add(p3);
        hs.add(p4);
        System.out.println(hs);
    }
}

输出

调用hashCode():844925
调用hashCode():756460
调用hashCode():844925
调用equals():true
调用hashCode():858572
[Person{name='林冲', age=31}, Person{name='李逵', age=28}, Person{name='宋江', age=41}]
  • 对TreeSet使用外部比较器
    外部比较器的优势在于可以随意定义多个,在TreeSet构造对象时通过传参自由决定使用什么比较器(比较规则)。
public class Test02 {
    public static void main(String[] args) {
        Comparator<Person> cmp=new MyComparator();
        TreeSet<Person> ts=new TreeSet<>(cmp);

        Person p1=new Person("酒保",18);
        Person p2=new Person("宋江",41);
        Person p3=new Person("酒保",30);
        Person p4=new Person("李逵",28);

        ts.add(p1);
        ts.add(p2);
        ts.add(p3);
        ts.add(p4);

		System.out.println("集合元素个数:"+ts.size());
        System.out.println(ts);

    }
}

class MyComparator implements Comparator<Person> {
    @Override
    public int compare(Person o1, Person o2) {
        Person p1 = (Person) o1;
        Person p2 = (Person) o2;
        if (p1.getName().compareTo(p2.getName()) > 0) {
            return -1;
        } else if (p1.getName().compareTo(p2.getName()) < 0) {
            return 1;
        } else {
            return p1.getAge() - p2.getAge();
        }
    }
}
  1. 迭代器
    提供统一的方式来遍历List/Set/Map。
  • 迭代器遍历List
public class Test {
    public static void main(String[] args) {
        List<String> aList = new ArrayList<String>();
        for (int i = 0; i < 5; i++) {
            aList.add("a" + i);
        }
        System.out.println(aList);
        for (Iterator<String> iter = aList.iterator(); iter.hasNext();) {
            String temp = iter.next();
            System.out.print(temp + "\t");
            if (temp.endsWith("3")) {// 删除3结尾的字符串
                iter.remove();
            }
        }
        System.out.println();
        System.out.println(aList);
    }
}
  • 迭代器遍历Set
public class Test {
    public static void main(String[] args) {
        Set<String> set = new HashSet<String>();
        for (int i = 0; i < 5; i++) {
            set.add("a" + i);
        }
        System.out.println(set);
        for (Iterator<String> iter = set.iterator(); iter.hasNext();) {
            String temp = iter.next();
            System.out.print(temp + "\t");
        }
        System.out.println();
        System.out.println(set);
    }
}
  • 迭代器遍历Map
//方式一:
public class Test {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("A", "高淇");
        map.put("B", "高小七");
        Set<Entry<String, String>> ss = map.entrySet();
        //增强for循环
        for(Entry<String, String> en : ss) {
        	System.out.println(en.getKey() + "\t" + en.getValue());
        }
        //for (Iterator<Entry<String, String>> iterator = ss.iterator(); iterator.hasNext();) {
        //    Entry<String, String> e = iterator.next();
        //    System.out.println(e.getKey() + "--" + e.getValue());
        //}
    }
}

//方式二:
public class Test {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("A", "高淇");
        map.put("B", "高小七");
        Set<String> ss = map.keySet();
        //增强for循环
        for(String key : ss) {
			System.out.println(key + "\t" + map.get(key));
		}
        //for (Iterator<String> iterator = ss.iterator(); iterator.hasNext();) {
        //    String key = iterator.next();
        //    System.out.println(key + "--" + map.get(key));
        //}
    }
}
  • 使用while循环遍历一般用于一边遍历一边添加/删除的方式。但需要使用ListIterator迭代器。ListIterator是Iterator迭代器的扩展,不仅支持正向遍历,还支持反向遍历。更重要的是可以一边遍历一边添加/删除容器内容。这种功能如果使用Iterator和容器对象实现会报ConcurrentModificationException异常。
ArrayList<String> a1 = new ArrayList<>();
a1.add("西门吹雪");
a1.add("叶孤城");
a1.add("陆小凤");
ListIterator<String> lit = a1.listIterator();
//遍历过程中动态添加元素
while (lit.hasNext()) {
    String str = lit.next();
    if ("陆小凤".equals(str)) {
        lit.add("花满楼");
    }
}
System.out.println(lit);
//逆向遍历
while (lit.hasPrevious()) {
    System.out.println(lit.previous());
}
  1. java.util.Collections工具类
    类 java.util.Collections 提供了对Set、List、Map进行排序、填充、查找元素的辅助方法。
  • void sort(List) //对List容器内的元素排序,排序的规则是按照升序进行排序。
  • void shuffle(List) //对List容器内的元素进行随机排列。
  • void reverse(List) //对List容器内的元素进行逆续排列 。
  • void fill(List, Object) //用一个特定的对象重写整个List容器。
  • int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的方法查找特定对象。
public class Test {
    public static void main(String[] args) {
        List<String> aList = new ArrayList<String>();
        for (int i = 0; i < 5; i++){
            aList.add("a" + i);
        }
        System.out.println(aList);
        Collections.shuffle(aList); // 随机排列
        System.out.println(aList);
        Collections.reverse(aList); // 逆续
        System.out.println(aList);
        Collections.sort(aList); // 排序
        System.out.println(aList);
        System.out.println(Collections.binarySearch(aList, "a2")); 
        Collections.fill(aList, "hello");
        System.out.println(aList);
    }
}
  1. 通过容器来实现ORM(Object Record Mapping)
    可以使用List/Set/Map灵活组合实现ORM。
  • 通过List+Map实现ORM
// Map是键值对的集合
Map<String, Object> row1 = new HashMap<>();
row1.put("id", 10);
row1.put("name", "周伯通");
row1.put("salary", 11000);
row1.put("age", 27);

Map<String, Object> row2 = new HashMap<>();
row2.put("id", 13);
row2.put("name", "紫衫龙王");
row2.put("salary", 28997);
row2.put("age", 27);

Map<String, Object> row3 = new HashMap<>();
row3.put("id", 21);
row3.put("name", "黄蓉");
row3.put("salary", 65243);
row3.put("age", 27);

Map<String, Object> row4 = new HashMap<>();
row4.put("id", 5);
row4.put("name", "郭靖");
row4.put("salary", 33526);
row4.put("age", 27);

// List是Map的集合
List<Map<String, Object>> table = new ArrayList<>();
table.add(row1);
table.add(row2);
table.add(row3);
table.add(row4);

for (Map<String, Object> row : table) {
	Set<String> cols = row.keySet();
	for (String col : cols) {
		System.out.print(col + ":" + row.get(col) + "\t");
	}
	System.out.println();
}

System.out.println("-------------------------------------");
for (Map<String, Object> row : table) {
	Set<String> cols = row.keySet();
	for (Iterator<String> it = cols.iterator(); it.hasNext();) {
		String col = it.next();
		System.out.print(col + ":" + row.get(col) + "\t");
	}
	System.out.println();
}
  • 通过JavaBean/POJO+List实现ORM
public class Test {
	public static void main(String[] args) {
		List<Staff> staffs = new ArrayList<>();
		staffs.add(new Staff(1, "貂蝉", 8746, 18));
		staffs.add(new Staff(2, "西施", 7736, 22));
		staffs.add(new Staff(3, "王昭君", 8765, 27));
		staffs.add(new Staff(4, "杨玉环", 7876, 30));

		for (Iterator<Staff> it = staffs.iterator(); it.hasNext();) {
			System.out.println(it.next());
		}
	}
}

/**
 * JavaBean
 * 
 * @author beeworkshop
 *
 */
class Staff {
	private int id;
	private String name;
	private int salary;
	private int age;

	// 一个完整的JavaBean需要有getter和setter方法,还要有一个空的无参构造器。
	// 一个JavaBean对应数据库表的一行/记录。

	public Staff() {

	}

	public Staff(int id, String name, int salary, int age) {
		super();
		this.id = id;
		this.name = name;
		this.salary = salary;
		this.age = age;
	}

	@Override
	public String toString() {
		return "[id=" + id + ", name=" + name + ", salary=" + salary + ", age=" + age + "]";
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getSalary() {
		return salary;
	}

	public void setSalary(int salary) {
		this.salary = salary;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值