第一个版本(会有线程安全问题)
StringBuilder str = new StringBuilder("dsakljdkluqioweknm,weqn,bqj,rrwq,mnkkwqjekljqwklejqwklwq,em,qwbmnbqwmnrbqwnmbrwqsadsadadgjklg");
str = new StringBuilder("uyuiyijkljkx,m,ccgeuioqejbnmewbmrnbwekjhjjxcv,m654876q123e123132456a4q8we85451231cz5456as4d568798wqeas9jkjcm-`1QMNJKHZMKJKLJIJIJCXVMNMNXBVHSBFHD");
ExecutorService service = Executors.newFixedThreadPool(4);
ConcurrentHashMap<Character, AtomicInteger> map = new ConcurrentHashMap<>();
ReentrantLock lock = new ReentrantLock();
int n = str.length() / 4;
for (int i = 0; i < str.length(); i = i + n) {
String ss = null;
if (str.length() - i <= n) {
ss = str.substring(i, str.length());
} else {
ss = str.substring(i, n + i);
}
final String s2 = ss;
service.execute(() -> {
for (int j = 0; j < s2.length(); j++
) {
char c = s2.charAt(j);
//这里会产生线程安全问题,如果多个线程同时
if (!map.containsKey(c)) {
map.put(c, new AtomicInteger(1));
System.out.println("线程:" + Thread.currentThread().getName() + "发现不存在:" + c);
} else {
System.out.println("线程:" + Thread.currentThread().getName() + "判断存在:" + c);
//保证原子操作,一开始用的Integer,会有线程安全问题
AtomicInteger atomicInteger = map.get(c);
atomicInteger.getAndIncrement();
}
}
});
}
service.shutdown();
while (!service.awaitTermination(2, TimeUnit.SECONDS)) {
Thread.yield();
}
//使用函数式编程求最小值
Map.Entry<Character, AtomicInteger> keyVal = map.entrySet().stream().min(Comparator.comparingInt(c -> c.getValue().get())).get();
System.out.println(keyVal);
//使用函数式编程对map进行排序
LinkedHashMap<Character, AtomicInteger> res = map.entrySet().stream().sorted((a, b) -> {
if (a.getValue().equals(b.getValue())) {
return a.getKey() - b.getKey();
} else {
return a.getValue().get() - b.getValue().get();
}
}).collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new ));
System.out.println(res);
这段代码会有线程安全的问题,我们测试一下看看数据
StringTest
Connected to the target VM, address: '127.0.0.1:57216', transport: 'socket'
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
线程:pool-1-thread-3发现不存在:e 这里就是线程安全的证明
线程:pool-1-thread-2发现不存在:e
线程:pool-1-thread-4发现不存在:-
线程:pool-1-thread-1发现不存在:u
线程:pool-1-thread-4发现不存在:`
线程:pool-1-thread-2发现不存在:k
线程:pool-1-thread-2发现不存在:j
线程:pool-1-thread-3发现不存在:8
线程:pool-1-thread-2发现不存在:h
线程:pool-1-thread-2判断存在:j
线程:pool-1-thread-4发现不存在:1
线程:pool-1-thread-1发现不存在:y
线程:pool-1-thread-2判断存在:j
线程:pool-1-thread-3发现不存在:5
线程:pool-1-thread-2发现不存在:x
线程:pool-1-thread-4发现不存在:Q
线程:pool-1-thread-1判断存在:u
线程:pool-1-thread-4发现不存在:M
线程:pool-1-thread-2发现不存在:c
线程:pool-1-thread-3发现不存在:4
线程:pool-1-thread-2发现不存在:v
线程:pool-1-thread-4发现不存在:N
线程:pool-1-thread-1发现不存在:i
线程:pool-1-thread-4发现不存在:J
线程:pool-1-thread-2发现不存在:,
线程:pool-1-thread-3判断存在:5
线程:pool-1-thread-4发现不存在:K
线程:pool-1-thread-1判断存在:y
线程:pool-1-thread-3判断存在:1
线程:pool-1-thread-1判断存在:i
线程:pool-1-thread-2发现不存在:m
线程:pool-1-thread-1判断存在:j
线程:pool-1-thread-3发现不存在:2
线程:pool-1-thread-4发现不存在:H
线程:pool-1-thread-3发现不存在:3
线程:pool-1-thread-1判断存在:k
线程:pool-1-thread-2发现不存在:6
线程:pool-1-thread-3判断存在:1
线程:pool-1-thread-3判断存在:c
线程:pool-1-thread-4发现不存在:Z
线程:pool-1-thread-3发现不存在:z
线程:pool-1-thread-1发现不存在:l
线程:pool-1-thread-1判断存在:j
线程:pool-1-thread-2判断存在:5
线程:pool-1-thread-1判断存在:k
线程:pool-1-thread-3判断存在:5
线程:pool-1-thread-3判断存在:4
线程:pool-1-thread-4判断存在:M
线程:pool-1-thread-3判断存在:5
线程:pool-1-thread-3判断存在:6
线程:pool-1-thread-1判断存在:x
线程:pool-1-thread-2判断存在:4
线程:pool-1-thread-1判断存在:,
线程:pool-1-thread-3发现不存在:a
线程:pool-1-thread-4判断存在:K
线程:pool-1-thread-3发现不存在:s
线程:pool-1-thread-1判断存在:m
线程:pool-1-thread-2判断存在:8
线程:pool-1-thread-1判断存在:,
线程:pool-1-thread-3判断存在:4
线程:pool-1-thread-4判断存在:J
线程:pool-1-thread-3发现不存在:d
线程:pool-1-thread-1判断存在:c
线程:pool-1-thread-1判断存在:c
线程:pool-1-thread-2发现不存在:7
线程:pool-1-thread-1发现不存在:g
线程:pool-1-thread-3判断存在:5
线程:pool-1-thread-4判断存在:K
线程:pool-1-thread-3判断存在:6
线程:pool-1-thread-1判断存在:e
线程:pool-1-thread-2判断存在:6
线程:pool-1-thread-2发现不存在:q
线程:pool-1-thread-1判断存在:u
线程:pool-1-thread-3判断存在:8
线程:pool-1-thread-4发现不存在:L
线程:pool-1-thread-3判断存在:7
线程:pool-1-thread-1判断存在:i
线程:pool-1-thread-2判断存在:1
线程:pool-1-thread-3发现不存在:9
线程:pool-1-thread-1发现不存在:o
线程:pool-1-thread-4判断存在:J
线程:pool-1-thread-1判断存在:q
线程:pool-1-thread-3判断存在:8
线程:pool-1-thread-2判断存在:2
线程:pool-1-thread-3发现不存在:w
线程:pool-1-thread-1判断存在:e
线程:pool-1-thread-1判断存在:j
线程:pool-1-thread-4发现不存在:I
线程:pool-1-thread-1发现不存在:b
线程:pool-1-thread-3判断存在:q
线程:pool-1-thread-2判断存在:3
线程:pool-1-thread-3判断存在:e
线程:pool-1-thread-1发现不存在:n
线程:pool-1-thread-4判断存在:J
线程:pool-1-thread-1判断存在:m
线程:pool-1-thread-3判断存在:a
线程:pool-1-thread-2判断存在:e
线程:pool-1-thread-3判断存在:s
线程:pool-1-thread-3判断存在:9
线程:pool-1-thread-3判断存在:j
线程:pool-1-thread-1判断存在:e
线程:pool-1-thread-4判断存在:I
线程:pool-1-thread-1判断存在:w
线程:pool-1-thread-3判断存在:k
线程:pool-1-thread-2判断存在:1
线程:pool-1-thread-2判断存在:2
线程:pool-1-thread-3判断存在:j
线程:pool-1-thread-1判断存在:b
线程:pool-1-thread-4判断存在:J
线程:pool-1-thread-1判断存在:m
线程:pool-1-thread-3判断存在:c
线程:pool-1-thread-2判断存在:3
线程:pool-1-thread-3判断存在:m
线程:pool-1-thread-1发现不存在:r
线程:pool-1-thread-4发现不存在:C
线程:pool-1-thread-1判断存在:n
线程:pool-1-thread-2判断存在:1
线程:pool-1-thread-1判断存在:b
线程:pool-1-thread-4发现不存在:X
线程:pool-1-thread-1判断存在:w
线程:pool-1-thread-2判断存在:3
线程:pool-1-thread-4发现不存在:V
线程:pool-1-thread-2判断存在:2
线程:pool-1-thread-4判断存在:M
线程:pool-1-thread-2判断存在:4
线程:pool-1-thread-2判断存在:5
线程:pool-1-thread-4判断存在:N
线程:pool-1-thread-2判断存在:6
线程:pool-1-thread-2判断存在:a
线程:pool-1-thread-4判断存在:M
线程:pool-1-thread-2判断存在:4
线程:pool-1-thread-4判断存在:N
线程:pool-1-thread-2判断存在:q
线程:pool-1-thread-4判断存在:X
线程:pool-1-thread-2判断存在:8
线程:pool-1-thread-2判断存在:w
线程:pool-1-thread-4发现不存在:B
线程:pool-1-thread-4判断存在:V
线程:pool-1-thread-4判断存在:H
线程:pool-1-thread-4发现不存在:S
线程:pool-1-thread-4判断存在:B
线程:pool-1-thread-4发现不存在:F
线程:pool-1-thread-4判断存在:H
线程:pool-1-thread-4发现不存在:D
-=1
{-=1, C=1, D=1, F=1, L=1, Q=1, S=1, Z=1, `=1, d=1, g=1, h=1, l=1, o=1, r=1, v=1, z=1, 7=2, 9=2, B=2, I=2, V=2, X=2, n=2, s=2, x=2, y=2, ,=3, H=3, K=3, N=3, a=3, b=3, i=3, u=3, 2=4, 3=4, M=4, k=4, q=4, w=4, 6=5, 8=5, J=5, c=5, m=5, 1=6, 4=6, e=6, 5=7, j=8}
Disconnected from the target VM, address: '127.0.0.1:57216', transport: 'socket'
Process finished with exit code 0
发现e被判断了两次不存在,所以这块是个非原子性的操作,加锁优化,看如下代码:
public static void main(String[] args) throws InterruptedException {
//StringBuilder str = new StringBuilder("dsakljdkluqioweknm,weqn,bqj,rrwq,mnkkwqjekljqwklejqwklwq,em,qwbmnbqwmnrbqwnmbrwqsadsadadgjklg");
StringBuilder str = new StringBuilder("uyuiyijkljkx,m,ccgeuioqejbnmewbmrnbwekjhjjxcv,m654876q123e123132456a4q8we85451231cz5456as4d568798wqeas9jkjcm-`1QMNJKHZMKJKLJIJIJCXVMNMNXBVHSBFHD");
ExecutorService service = Executors.newFixedThreadPool(4);
ConcurrentHashMap<Character, AtomicInteger> map = new ConcurrentHashMap<>();
ReentrantLock lock = new ReentrantLock();
int n = str.length() / 4;
for (int i = 0; i < str.length(); i = i + n) {
String ss = null;
if (str.length() - i <= n) {
ss = str.substring(i, str.length());
} else {
ss = str.substring(i, n + i);
}
final String s2 = ss;
service.execute(() -> {
for (int j = 0; j < s2.length(); j++
) {
char c = s2.charAt(j);
//这里会产生线程安全问题
if (!map.containsKey(c)) {
lock.lock();
//还需要做一次判断,防止多线程阻塞到这里
if (!map.containsKey(c)) {
System.out.println("线程:" + Thread.currentThread().getName() + "发现不存在:" + c);
map.put(c, new AtomicInteger(1));
} else {
System.out.println("线程:" + Thread.currentThread().getName() + "第二次判断存在:" + c);
AtomicInteger atomicInteger = map.get(c);
atomicInteger.getAndIncrement();
}
lock.unlock();
} else {
System.out.println("线程:" + Thread.currentThread().getName() + "判断存在:" + c);
//保证原子操作,一开始用的Integer,会有线程安全问题
AtomicInteger atomicInteger = map.get(c);
atomicInteger.getAndIncrement();
}
}
});
}
service.shutdown();
while (!service.awaitTermination(2, TimeUnit.SECONDS)) {
Thread.yield();
}
//使用函数式编程求最小值
Map.Entry<Character, AtomicInteger> keyVal = map.entrySet().stream().min((a, b) -> {
if (a.getValue().equals(b.getValue())) {
return a.getKey() - b.getKey();
} else {
return a.getValue().get() - b.getValue().get();
}
}).get();
System.out.println(keyVal);
LinkedHashMap<Character, AtomicInteger> res = map.entrySet().stream().sorted((a, b) -> {
if (a.getValue().equals(b.getValue())) {
return a.getKey() - b.getKey();
} else {
return a.getValue().get() - b.getValue().get();
}
}).collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new ));
System.out.println(res);
}
我们看看结果:
StringTest
Connected to the target VM, address: '127.0.0.1:51540', transport: 'socket'
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
线程:pool-1-thread-1发现不存在:u
线程:pool-1-thread-1发现不存在:y
线程:pool-1-thread-1判断存在:u
线程:pool-1-thread-4发现不存在:-
线程:pool-1-thread-4发现不存在:`
线程:pool-1-thread-4发现不存在:1
线程:pool-1-thread-4发现不存在:Q
线程:pool-1-thread-4发现不存在:M
线程:pool-1-thread-4发现不存在:N
线程:pool-1-thread-4发现不存在:J
线程:pool-1-thread-4发现不存在:K
线程:pool-1-thread-4发现不存在:H
线程:pool-1-thread-3发现不存在:e
线程:pool-1-thread-3发现不存在:8
线程:pool-1-thread-3发现不存在:5
线程:pool-1-thread-3发现不存在:4
线程:pool-1-thread-3判断存在:5
线程:pool-1-thread-2第二次判断存在:e
线程:pool-1-thread-3判断存在:1
线程:pool-1-thread-2发现不存在:k
线程:pool-1-thread-2发现不存在:j
线程:pool-1-thread-2发现不存在:h
线程:pool-1-thread-2判断存在:j
线程:pool-1-thread-1发现不存在:i
线程:pool-1-thread-2判断存在:j
线程:pool-1-thread-4发现不存在:Z
线程:pool-1-thread-1判断存在:y
线程:pool-1-thread-3发现不存在:2
线程:pool-1-thread-4判断存在:M
线程:pool-1-thread-3发现不存在:3
线程:pool-1-thread-1判断存在:i
线程:pool-1-thread-2发现不存在:x
线程:pool-1-thread-3判断存在:1
线程:pool-1-thread-4判断存在:K
线程:pool-1-thread-2发现不存在:c
线程:pool-1-thread-1判断存在:j
线程:pool-1-thread-4判断存在:J
线程:pool-1-thread-1判断存在:k
线程:pool-1-thread-4判断存在:K
线程:pool-1-thread-2发现不存在:v
线程:pool-1-thread-2发现不存在:,
线程:pool-1-thread-2发现不存在:m
线程:pool-1-thread-2发现不存在:6
线程:pool-1-thread-2判断存在:5
线程:pool-1-thread-3第二次判断存在:c
线程:pool-1-thread-2判断存在:4
线程:pool-1-thread-3发现不存在:z
线程:pool-1-thread-2判断存在:8
线程:pool-1-thread-1发现不存在:l
线程:pool-1-thread-3判断存在:5
线程:pool-1-thread-4发现不存在:L
线程:pool-1-thread-3判断存在:4
线程:pool-1-thread-1判断存在:j
线程:pool-1-thread-3判断存在:5
线程:pool-1-thread-2发现不存在:7
线程:pool-1-thread-4判断存在:J
线程:pool-1-thread-2判断存在:6
线程:pool-1-thread-3判断存在:6
线程:pool-1-thread-1判断存在:k
线程:pool-1-thread-4发现不存在:I
线程:pool-1-thread-1判断存在:x
线程:pool-1-thread-2发现不存在:q
线程:pool-1-thread-4判断存在:J
线程:pool-1-thread-3发现不存在:a
线程:pool-1-thread-4判断存在:I
线程:pool-1-thread-2判断存在:1
线程:pool-1-thread-1判断存在:,
线程:pool-1-thread-2判断存在:2
线程:pool-1-thread-4判断存在:J
线程:pool-1-thread-3发现不存在:s
线程:pool-1-thread-2判断存在:3
线程:pool-1-thread-1判断存在:m
线程:pool-1-thread-3判断存在:4
线程:pool-1-thread-4发现不存在:C
线程:pool-1-thread-2判断存在:e
线程:pool-1-thread-4发现不存在:X
线程:pool-1-thread-1判断存在:,
线程:pool-1-thread-4发现不存在:V
线程:pool-1-thread-2判断存在:1
线程:pool-1-thread-3发现不存在:d
线程:pool-1-thread-4判断存在:M
线程:pool-1-thread-1判断存在:c
线程:pool-1-thread-4判断存在:N
线程:pool-1-thread-3判断存在:5
线程:pool-1-thread-2判断存在:2
线程:pool-1-thread-3判断存在:6
线程:pool-1-thread-4判断存在:M
线程:pool-1-thread-1判断存在:c
线程:pool-1-thread-4判断存在:N
线程:pool-1-thread-3判断存在:8
线程:pool-1-thread-2判断存在:3
线程:pool-1-thread-3判断存在:7
线程:pool-1-thread-4判断存在:X
线程:pool-1-thread-1发现不存在:g
线程:pool-1-thread-2判断存在:1
线程:pool-1-thread-3发现不存在:9
线程:pool-1-thread-1判断存在:e
线程:pool-1-thread-4发现不存在:B
线程:pool-1-thread-3判断存在:8
线程:pool-1-thread-2判断存在:3
线程:pool-1-thread-3发现不存在:w
线程:pool-1-thread-4判断存在:V
线程:pool-1-thread-1判断存在:u
线程:pool-1-thread-4判断存在:H
线程:pool-1-thread-3判断存在:q
线程:pool-1-thread-2判断存在:2
线程:pool-1-thread-3判断存在:e
线程:pool-1-thread-4发现不存在:S
线程:pool-1-thread-1判断存在:i
线程:pool-1-thread-4判断存在:B
线程:pool-1-thread-3判断存在:a
线程:pool-1-thread-2判断存在:4
线程:pool-1-thread-3判断存在:s
线程:pool-1-thread-1发现不存在:o
线程:pool-1-thread-3判断存在:9
线程:pool-1-thread-2判断存在:5
线程:pool-1-thread-3判断存在:j
线程:pool-1-thread-1判断存在:q
线程:pool-1-thread-4发现不存在:F
线程:pool-1-thread-1判断存在:e
线程:pool-1-thread-3判断存在:k
线程:pool-1-thread-1判断存在:j
线程:pool-1-thread-2判断存在:6
线程:pool-1-thread-1发现不存在:b
线程:pool-1-thread-2判断存在:a
线程:pool-1-thread-3判断存在:j
线程:pool-1-thread-4判断存在:H
线程:pool-1-thread-3判断存在:c
线程:pool-1-thread-2判断存在:4
线程:pool-1-thread-3判断存在:m
线程:pool-1-thread-2判断存在:q
线程:pool-1-thread-2判断存在:8
线程:pool-1-thread-2判断存在:w
线程:pool-1-thread-1发现不存在:n
线程:pool-1-thread-1判断存在:m
线程:pool-1-thread-4发现不存在:D
线程:pool-1-thread-1判断存在:e
线程:pool-1-thread-1判断存在:w
线程:pool-1-thread-1判断存在:b
线程:pool-1-thread-1判断存在:m
线程:pool-1-thread-1发现不存在:r
线程:pool-1-thread-1判断存在:n
线程:pool-1-thread-1判断存在:b
线程:pool-1-thread-1判断存在:w
-=1
{-=1, C=1, D=1, F=1, L=1, Q=1, S=1, Z=1, `=1, d=1, g=1, h=1, l=1, o=1, r=1, v=1, z=1, 7=2, 9=2, B=2, I=2, V=2, X=2, n=2, s=2, x=2, y=2, ,=3, H=3, K=3, N=3, a=3, b=3, i=3, u=3, 2=4, 3=4, M=4, k=4, q=4, w=4, 6=5, 8=5, J=5, c=5, m=5, 1=6, 4=6, 5=7, e=7, j=8}
Disconnected from the target VM, address: '127.0.0.1:51540', transport: 'socket'
Process finished with exit code 0
是正确的:我们也可以拿单线程的去跑对比下最后按照大小排序的map
给上单线程跑的代码:
@Test
public void test() {
StringBuilder sb = new StringBuilder("uyuiyijkljkx,m,ccgeuioqejbnmewbmrnbwekjhjjxcv,m654876q123e123132456a4q8we85451231cz5456as4d568798wqeas9jkjcm-`1QMNJKHZMKJKLJIJIJCXVMNMNXBVHSBFHD");
HashMap<Character, Integer> map = new HashMap<>();
for (Character c : sb.toString().toCharArray()
) {
if (!map.containsKey(c)) {
map.put(c, 1);
} else {
map.put(c, map.get(c) + 1);
}
}
LinkedHashMap<Character, Integer> res = map.entrySet().stream().sorted((a, b) -> {
if (a.getValue().equals(b.getValue())) {
return a.getKey() - b.getKey();
} else {
return a.getValue() - b.getValue();
}
}).collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new ));
System.out.println(res);
}