List集合的遍历方式
1.普通for循环,使用size()和get()方法
2.调用iterator()方法,使用hasNext()和next()方法
3.增强for循环,只要可以用迭代器的都可以用增强for循环
4.Vector集合特有的遍历方式,可以使用枚举Enumeration的hasMoreElements()和nextElement()方法
set集合没有索引所以少了两种
一种是迭代器
另一种是增强For循环
普通For循环,迭代器,增强for循环是否可以在在遍历中删除
</pre><pre name="code" class="java"><span style="font-family: Arial, Helvetica, sans-serif;"> public static void main(String[] args) {</span>
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("b");
list.add("d");
list.add("e");
/*for(int i = 0; i < list.size(); i++) { //普通for循环可以删除,但是索引要--
if(list.get(i).equals("b")) {
list.remove(i--);
}
}*/
/*Iterator<String> it = list.iterator();
while(it.hasNext()) {
String temp = it.next();
if(temp.equals("b")) {
//list.remove("b"); //不能用集合的删除方法,会报出并发修改异常
it.remove(); //迭代器可以删除,但是必须用迭代器的删除方法
}
}*/
for (String s : list) { //增强for循环是不可以删除的
if(s.equals("b")) {
list.remove("b");
}
}
System.out.println(list);
}
}
Set集合特点
List
有序(存和取是一致的),有索引,可以重复
Set
无序(存和取不是一致的),无索引,不可以重复
HashSet原理
1. 使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
如果没有哈希值相同的对象就直接存入集合
如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
2.将自定义类的对象存入HashSet去重复
类中必须重写hashCode()和equals()方法
hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储
LinkedHashSet的特点
public static void main(String[] args) {
LinkedHashSet<String> lh = new LinkedHashSet<>(); //可以怎么存就怎么取
lh.add("a");
lh.add("a");
lh.add("b");
lh.add("c");
lh.add("d");
System.out.println(lh);//并去掉重复[a, b, c, d]
}
<pre name="code" class="java"><pre name="code" class="java">public static void main(String[] args) {
// 将集合中的重复元素去掉
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("a");
list.add("a");
list.add("a");
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("b");
list.add("c");
list.add("c");
getSingel(list);//调用方法,没有放回值类型可以直接方法名调用
System.out.println(list);
System.out.println("-----------------------------------");
// getSingel2(list);
// System.out.println(list);
}
/*
* 返回值类型void
* 参数列表ArrayList<String> list*/
public static void getSingel(ArrayList<String> list){
HashSet<String> hs = new HashSet<>();//创建HashSet对象
hs.addAll(list); //将list中的元素逐一存储到黑hs集合当中,hs会将集合中的重复去掉,得到新的集合
list.clear(); //清空原集合
list.addAll(hs); //将新集和放入list中################运用HashSet操作得到的是没有顺序的集合
}
// public static void getSingel2(List<String> list){
// LinkedHashSet<String> lhs = new LinkedHashSet<>();
// lhs.addAll(list);
// list.clear();
// list.addAll(lhs);//###########运用linkedHashSet操作得到的是有有序的集合
// }
}
TreeSet集合
TreeSet集合可以对集合中的元素排序、、、根据码表值排序
TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
使用方式
自然顺序(Comparable)
TreeSet类的add()方法中会把存入的对象提升为Comparable类型
调用对象的compareTo()方法和集合中的对象比较
根据compareTo()方法返回的结果进行存储
比较器顺序(Comparator)
创建TreeSet的时候可以制定 一个Comparator
如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
add()方法内部会自动调用Comparator接口中compare()方法排序
两种方式的区别
TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
TreeSet如果传入Comparator, 就优先按照Comparator
// 在一个集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且还不能去除重复
public static void main(String[] args) {
List <String> list = new ArrayList<>();
list.add("aaaa");
list.add("eeeee");
list.add("aaaa");
list.add("cc");
list.add("ddd");
list.add("bbbbbbb");
getSingel(list);
System.out.println(list);
}
/*TreeSet
* List<String> list*/
public static void getSingel(List<String> list){
TreeSet<String> ts = new TreeSet<>(new Comparator<String>(){//创建TreeSet集合对象并传入比较器
@Override
public int compare(String s1, String s2) {
int num = s1.compareTo(s2);
return num == 0? 1 : num;//比较两个元素是否相同,如果相同num== 0那么返回1.也就是排在后面
}});
ts.addAll(list);//将集合中的元素添加到,也就是对元素进行排序
list.clear(); //将原集合清空
list.addAll(ts);//将新集和添加到原集合中
}
</pre><p></p><p><strong><span style="font-size:14px;">Map集合是双列集合</span></strong></p><p> 一次可以存储两个对象 ,一个是键,一个是值,键对象集合中是唯一的可以通过键查找值</p><p><strong>Map接口和Collection接口的不同</strong><span style="color:rgb(128,128,128)"> </span>Map是双列的,Collection是单列的<span style="color:#808080"> </span>Map的键唯一,Collection的子体系Set是唯一的<span style="color:#808080"> </span>Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素</p><p><strong><span style="font-size:14px;">Map集合的功能</span></strong></p><p></p><pre name="code" class="java">public class Map集合的功能和两种遍历方式 {
// HashSet底层依赖于HashMap
// * TreeSet底层依赖于TreeMap
public static void main(String[] args) {
HashMap<String,String> hm = new HashMap<>();
String s1 = hm.put("李四", "北京");//第一次储存返回的是null
String s2 = hm.put("李四", "天津");//第二次储存返回的是被覆盖的值
String s3 = hm.put("王五", "上海");//HashMap 的键是唯一的
String s4 = hm.put("王五", "南京");
String s5 = hm.put("哈哈", "重庆");
String s6 = hm.put("哈尼", "重庆");//HashMap 的值不是唯一的
System.out.println(s1);//null
System.out.println(s2);//北京
System.out.println(s3);//null
System.out.println(s4);//上海
System.out.println(s5);//null
System.out.println(s6);//null
/* //hm.clear(); //将HashMap集合清空
System.out.println(hm);
boolean b1 = hm.containsKey("李四");
System.out.println(b1);//看集合中是否包含键
boolean b2 = hm.containsValue("北京");
boolean b3 = hm.containsValue("保定");
System.out.println(b2);
System.out.println(b3);*///看集合中是否包含值
//System.out.println(hm.hashCode());//返回集合哈希值4379639
//hm.clear();
//System.out.println(hm.isEmpty());//看集合是否为空
//String s = hm.get("我");根据键获取值如果没有就返回null
//String s2 = hm.get("哈哈");
//System.out.println(s);null
//System.out.println(s2);重庆
//System.out.println(hm.remove("李四"));//根据键删除键值对并将值返回
//System.out.println(hm);北京
//System.out.println(hm.size());//返回集合中键值对的个数
//System.out.println(hm.values());//获取所有值的集合
/*
*
*
* 下面是Map集合的遍历之键值对对象找键和值 应用的是entrySet方法
*/
/*Set<Map.Entry<String, String>> entrySet = hm.entrySet();//获取所有键值对的集合
Iterator<Entry<String, String>> it = entrySet.iterator();//获取迭代器
while(it.hasNext()){//判断集合中是否有元素
Entry<String,String> en = it.next();//获取键值对对象
String key = en.getKey();//获取键
String value = en.getValue();//获取值
System.out.println(key+ "=" + value);
}
System.out.println("---------------------------");
//用增强for循环
for (Entry<String, String> en : hm.entrySet()) {
System.out.println(en.getKey()+ " " + en.getValue());
}
/*
*
*
* 下面是对Map集合的遍历之键找值 应用的是keyset方法
Set<String> keySet = hm.keySet();//获取集合中的键
Iterator<String> it = keySet.iterator();//获取迭代器
while(it.hasNext()){//判断单列集合中是否有元素
String key = it.next();//获取集合中的元素,这里的元素就是键
String value = hm.get(key);//根据键获取值
System.out.println(key + "=" +value);
}
System.out.println("---------------------------");
//增强for循环
for(String key : hm.keySet()){
System.out.println(key+ "=" +hm.get(key));
}*/
}
}
HashMap集合当键是Stirng值是String以及键是对象值是String
<pre name="code" class="java">public static void main(String[] args) {
//demo1();
HashMap<String,String> hm = new HashMap<>();
//只要存入 键值元素保证元素不重复
hm.put("b", "4");
hm.put("a", "3");
hm.put("c", "5");
hm.put("e", "2");
hm.put("d", "1");
System.out.println(hm);
}
private static void demo1() {
//HashMap想保证键的唯一依赖于hashCode()和equals方法
HashMap<Person,String> hm = new HashMap<>();
hm.put(new Person("李虎",23), "北京");
hm.put(new Person("张龙",33), "海南");
hm.put(new Person("赵虎",27), "青岛");
hm.put(new Person("李虎",23), "北京");
System.out.println(hm);
}
LinkedHashMap的特点
public class DemoLinkedHashMap {
public static void main(String[] args) {
LinkedHashMap<String,String> lhm = new LinkedHashMap<>();
lhm.put("李四", "北京");//可以保证怎么存就怎么取
lhm.put("张三", "南京");
lhm.put("王五", "上海");
System.out.println(lhm);
}
TreeMap集合键是String值是String以及键是对象值是String
public class DemoTreeMap当键是person和键是String {
public static void main(String[] args) {
TreeMap <Person,String>tm = new TreeMap<>(new Comparator<Person>(){//也可传入比较器
@Override
public int compare(Person o1, Person o2) {
int num = o1.getName().compareTo(o2.getName());
return num==0?o1.getAge()-o2.getAge():1;//这里的写法与在对象里重写有所不同那边用的是this
}});// 对对象的比较需要需要在对象当中重写Hashcold和equals方法
//java.lang.ClassCastException:
tm.put(new Person("李华",23),"北极" );
tm.put(new Person("网虫",25),"南极" );
tm.put(new Person("混子",29),"山沟" );
System.out.println(tm);
//demo1();
}
private static void demo1() {
TreeMap <String,String>tm = new TreeMap<>();//根据输出结果可以看出TreeMap比较的是键
tm.put("b", "4");
tm.put("a", "3");
tm.put("c", "5");
tm.put("e", "2");
tm.put("d", "1");
System.out.println(tm);//{a=3, b=4, c=5, d=1, e=2}
}
}
集合嵌套之HashMap嵌套HashMap
public class HashMap嵌套HashMap {
public static void main(String[] args) {
HashMap<String,HashMap<Person,String>> hm = new HashMap<>();//创建HashMap对象键是String,值是HashMap
HashMap<Person,String> java01 = new HashMap<>();//创建HashMap集合对象键是Person,值是String
java01.put(new Person("李明",23), "北京");
java01.put(new Person("张三",33), "山西");
java01.put(new Person("李化",28), "新疆");
java01.put(new Person("赵丽",29), "北海");
HashMap<Person,String> java02 = new HashMap<>();//创建HashMap集合对象 键是Person,值是String
java02.put(new Person("小明",23), "大同");
java02.put(new Person("张良",33), "西安");
java02.put(new Person("永吉",28), "怀化");
hm.put("java基础班01", java01);
hm.put("java基础班02", java02);
for (String key :hm.keySet() ) { //遍历嵌套集合,String key代表hm 中的所有键
HashMap<Person,String> value = hm.get(key); //根据键获取的值是HashMap集合对象
for (Person k : value.keySet()) {//遍历集合对象
System.out.print(key+","+k+","+value.get(k)+"\t");
}//根据HashMap的特点打印结果,Java01和Java02顺序可能会颠倒
System.out.println();
}
}
HashMap和Hashtable的区别
public static void main(String[] args) {
/*HashMap和Hashtable的区别?
* 1.HashMap和Hashtable都是哈希算法
*
* 2.HashMap是jdk。1.2版本出来的,线程不安全,效率快;
* Hashtable是jdk1.0版本出来的,线程安全,效率低
*
* 3.HashMap中键,值都可以为null
* Hasheable中键和值不能为null*/
HashMap<String,String> hm = new HashMap<>();
hm.put("abc", null);
hm.put(null, "abc");
System.out.println(hm);//{null=abc, abc=null}
Hashtable<String,String> ht = new Hashtable<>();
ht.put("abc", null);
ht.put(null, "abc");
System.out.println(ht);// java.lang.NullPointerException
}
Collections类
public class DemoCollections {
/*
* Collections和Collection的区别是
* Collection是集合的跟接口
* Collections是集合的工具类,,其中方法都是静态的可以直接Collections.调用其中的方法
*
* public static <T> void sort(List<T> list)
public static <T> int binarySearch(List<?> list,T key)
public static <T> T max(Collection<?> coll)
public static void reverse(List<?> list)
public static void shuffle(List<?> list)*/
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("c");
list.add("a");
list.add("d");
list.add("x");
list.add("e");
Collections.sort(list);
System.out.println(list);//[a, c, d, e, x]sort 对集合中的方法进行排序
int index = Collections.binarySearch(list, "e");
System.out.println(index);//3 利用二分查找法对指定元素的索引
String s = Collections.max(list);
System.out.println(s);//x 找集合中最大的
Collections.replaceAll(list, "x", "w");//替换集合中所有的指定元素
System.out.println(list);//[a, c, d, e, w]
Collections.reverse(list);
System.out.println(list);//[w, e, d, c, a]将集合中的所用元素反转
Collections.shuffle(list);
System.out.println(list);//[w, a, d, e, c]使用默认随机源对集合中元素进行置换,此方法可用于模拟发牌
}
}
高级泛型
? extends E ?是子类E是父类,父类固定,子类和本类的元素都可以向内添加
? super E ?是父类 E是子类,子类固定子类可以调用父类方法