Collection集合特点(1) 1).Collection是集合类的根接口,Java中没有提供这个接口的直接的实现类。但有继承该类的两大接口类,就是List和 set集合,set集合不能包含重复的元素,List集合是一个有序的集合,可以包含重复的元素。 2)Map集合Java.util包中的另一个接口,它和Collection接口没有关系,是相互独立的,但是都属于集合类的一部分。和 collection集合最大的区别就是,Map集合是双列的,一般是成对出现的,即(键,值)总是以键值对出现。 风一般的逍遥: 3.java中的单列结合 java单列结合的家族中,collection是根接口,其下有两个继承子类List和Set集合。 List又有ArrayList,vector,LinkedList三个子类 Set有Hashset和Treeset两个子类 3.1 单列各个集合底层数据结构和基本性质 一.List集合:(有序,元素可以重复) 1.ArrayList集合: 1).底层数据结构是数组,查找快,增删慢。 2). 线程不安全,效率高 2.Vector集合: 1) 底层数据结构是数组,查询快,增删慢 2)线程安全,效率低 3.LinkedList集合: 1) 底层数据结构是链表,查询慢,增删快 2)线程不安全,效率高 风一般的逍遥: 二、Set集合(元素不可重复,元素唯一) 1.Hashset集合: 1) 底层数据结构是哈希表,哈希表依赖两个方法hascode ()和equals()方法 2)两个方法的执行顺序: 首先判断hascode()值是否相同 是:继续执行equals()方法,看其返回值 是true:说明元素重复,不添加 是false:就直接添加元素 否:就直接添加到集合 2.Treeset集合: 1)底层数据结构是二叉树 风一般的逍遥: 4.java的双列集合 1. java中的Map集合是双列的,Map集合是Map集合家族的根接口,它有HashMap和TreeMap集合两个子类。 2. Map集合中只对键有效,而对值是无效的。 3.子类的数据结构: Hashmap:底层数据结构是哈希表,Treemap底层数据结构是二叉树,其性质和Set的底层数据结构一样。 计算出生到现在过了多少天(2) package com.itheima.demo01;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
public class TestBirthday {
public static void main(String[]args) throws ParseException {
SimpleDateFormat sdf = newSimpleDateFormat("yyyy-MM-dd");
Scanner sc = new Scanner(System.in);
System.out.println("请输入您的生日:");
String birthday = sc.next();
Date bd = sdf.parse(birthday);
long time1 = bd.getTime();
Date now = new Date();
long time2 = now.getTime();
System.out.println("您的生存时长为:" + ((time2 - time1) / 1000 / 60 /60 / 24) + "天");
}
} 集合(3) ackage com.itheima.demo02;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
给定以下代码,请定义方法publicstatic int listTest(Collection<String> list,String s)统计集合中指定元素出现的次数,如"a":2,"b":2,"c" :1, "xxx":0。
Collection<String> list =new ArrayList<>();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c");
System.out.println("a:"+listTest(list,"a"));
System.out.println("b:"+listTest(list,"b"));
System.out.println("c:"+listTest(list,"c"));
System.out.println("xxx:"+listTest(list,"xxx"));
*/
@SuppressWarnings("all")
public class Day02Test01 {
public static void main(String[]args) {
Collection<String> list =new ArrayList<>();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c");
System.out.println("a:"+listTest(list, "a"));
System.out.println("b:"+listTest(list, "b"));
System.out.println("c:"+listTest(list, "c"));
System.out.println("xxx:"+listTest(list, "xxx"));
}
public static intlistTest(Collection<String> list,String s){
int a = 0;
Iterator<String> it =list.iterator();
while(it.hasNext()){
String n = it.next();
if (n.equals(s)){
a++;
}
}
return a;
}
} **String类中的常用方法(4) (1)booleanisEmpty(): 判断字符串是不是空串,如果是空的就返回true (2)charcharAt(int index): 返回索引上的字符 (3)StringtoLowerCase(): 字符串转成小写 (4)StringtoUpperCase(): 字符串转成大写 (5)Stringrepalce(char oldChar, char newChar): 将字符串中的老字符,替换为新字符 (6)Stringrepalce(String old, String newstr): 将字符串中的老字符串,替换为新字符串 (7)Stringtrim(): 去掉字符串两端空格 8)public?int?indexOf?(String?str) :返回指定子字符串第一次出现在该字符串内的索引。 (9)public?String?substring?(int?beginIndex,?int?endIndex):返回一个子字符串,从beginIndex到 endIndex截取字符串。含beginIndex,不含endIndex。 1. 编写程序将“jdk” 全部变为大写,并输出到屏幕,截取子串”DK” 并输出到屏幕 2.分析以下需求,并用代码实现: (1)定义如下方法public static StringgetPropertyGetMethodName(String property); (2)该方法的参数为String类型,表示用户给定的成员变量的名字,返回值类型为String类型,返回值为成员变量对应的get方法的名字 (3)如:用户调用此方法时给定的参数为"name",该方法的返回值为"getName" 3.分析以下需求,并用代码实现: (1)定义数字字符串数组{"010","3223","666","7890987","123123"} (2)判断该数字字符串数组中的数字字符串是否是对称(第一个数字和最后一个数字相等,第二个数字和倒数第二个数字是相等的,依次类推)的,并逐个输出 (3)如:010 是对称的,3223 是对称的,123123 不是对称的 (4)最终打印该数组中对称字符串的个数 提示:循环获取字符串的每一个字符,依次比较第一个和最后一个,第二个和倒数第二个。。。 4.分析以下需求,并用代码实现: (1)从键盘录入一个字符串 (2)将字符串中大写字母变成小写字母,小写字母变成大写字母,其它字符用"*"代替,并统计字母的个数 举例: 键盘录入:Hello12345World 输出结果:hELLO*****wORLD 总共10个字母 5.分析以下需求,并用代码实现: (1)定义一个方法 publicObject[] deleteSubString(String str1,String str2) { } (2)方法功能描述:从str1中删除所有的str2,并返回删除后的结果,返回结果为Object[]数组 * 该数组的第一个元素为删除所有的str2后的最终的字符串 * 该数组的第二个元素为删除的str2的个数 6. 给定一个字符串,判断该字符串中是否包含某个子串.如果包含,求出子串的所有出现位置. 如:"abcbcbabcb34bcbd"中,"bcb"子串的出现位置为: 1,7,12.字符串和子串均由用户输入 7.给定一个长度,随机产生一个该长度的字符串,由大写,小写字母以及数字组成 Java中随机数的生成: java.util.Randomr = new java.util.Random(); int a =r.nextInt(100): a 0-99的随机数 synchronized与Lock的区别(5) 两者区别: 1.首先synchronized是java内置关键字,在jvm层面,Lock是个java类; 2.synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁; 3.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁; 4.用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了; 5.synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可) 6.Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。 小例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | package com.cn.test.thread.lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockTest { private Lock lock = new ReentrantLock(); /* * 使用完毕释放后其他线程才能获取锁 */ public void lockTest(Thread thread) { lock.lock();//获取锁 try { System.out.println("线程"+thread.getName() + "获取当前锁"); //打印当前锁的名称 Thread.sleep(2000);//为看出执行效果,是线程此处休眠2秒 } catch (Exception e) { System.out.println("线程"+thread.getName() + "发生了异常释放锁"); }finally { System.out.println("线程"+thread.getName() + "执行完毕释放锁"); lock.unlock(); //释放锁 } } public static void main(String[] args) { LockTest lockTest = new LockTest(); //声明一个线程 “线程一” Thread thread1 = new Thread(new Runnable() { @Override public void run() { lockTest.lockTest(Thread.currentThread()); } }, "thread1"); //声明一个线程 “线程二” Thread thread2 = new Thread(new Runnable() { @Override public void run() { lockTest.lockTest(Thread.currentThread()); } }, "thread2"); // 启动2个线程 thread2.start(); thread1.start(); } } |
执行结果: [url=]file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image001.png[/url] package com.cn.test.thread.lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockTest { private Lock lock = newReentrantLock(); /* * 尝试获取锁 tryLock() 它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false */ public void tryLockTest(Thread thread) { if(lock.tryLock()){ //尝试获取锁 try { System.out.println("线程"+thread.getName() + "获取当前锁"); //打印当前锁的名称 Thread.sleep(2000);//为看出执行效果,是线程此处休眠2秒 } catch(Exception e) { System.out.println("线程"+thread.getName() + "发生了异常释放锁"); }finally { System.out.println("线程"+thread.getName() + "执行完毕释放锁"); lock.unlock(); //释放锁 } }else{ System.out.println("我是线程"+Thread.currentThread().getName()+"当前锁被别人占用,我无法获取"); } } public static void main(String[] args) { LockTest lockTest = new LockTest(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { lockTest.tryLockTest(Thread.currentThread()); } }, "thread1"); //声明一个线程 “线程二” Thread thread2 = new Thread(new Runnable() { @Override public void run() { lockTest.tryLockTest(Thread.currentThread()); } }, "thread2"); // 启动2个线程 thread2.start(); thread1.start(); } } [url=]file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image001.png[/url] 执行结果: [url=]file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image001.png[/url] package com.cn.test.thread.lock; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockTest { private Lock lock = newReentrantLock(); public void tryLockParamTest(Thread thread) throws InterruptedException { if(lock.tryLock(3000,TimeUnit.MILLISECONDS)) { //尝试获取锁 获取不到锁,就等3秒,如果3秒后还是获取不到就返回false try { System.out.println("线程"+thread.getName() + "获取当前锁"); //打印当前锁的名称 Thread.sleep(4000);//为看出执行效果,是线程此处休眠2秒 } catch(Exception e) { System.out.println("线程"+thread.getName() + "发生了异常释放锁"); }finally { System.out.println("线程"+thread.getName() + "执行完毕释放锁"); lock.unlock(); //释放锁 } }else{ System.out.println("我是线程"+Thread.currentThread().getName()+"当前锁被别人占用,等待3s后仍无法获取,放弃"); } } public static void main(String[] args) { LockTest lockTest = new LockTest(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { try { lockTest.tryLockParamTest(Thread.currentThread()); } catch(InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, "thread1"); //声明一个线程 “线程二” Thread thread2 = new Thread(new Runnable() { @Override public void run() { try { lockTest.tryLockParamTest(Thread.currentThread()); } catch(InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, "thread2"); // 启动2个线程 thread2.start(); thread1.start(); } } [url=]file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image001.png[/url] 执行结果: 因为此时线程1休眠了4秒,线程2等待了3秒还没有获取到就放弃获取锁了,执行结束 将方法中的 Thread.sleep(4000)改为Thread.sleep(2000)执行结果如下: 因为此时线程1休眠了2秒,线程2等待了3秒的期间线程1释放了锁,此时线程2获取到锁,线程2就可以执行了
|