1. HashMap特点
是无序的: 不能保证 存储 和取出的元素顺序一致。
2.HashMap底层逻辑
3. 值位置存储自定义对象
// keep statistics for each client
public class Stats{
public int clientNum;
public static int nextNum = 0;
public double oneWayDelay;
public boolean delayReady = false;
public HashSet<Integer> prevPose = new HashSet<>();
public HashMap<Integer, Long> videoSendTime = new HashMap<>();
public HashMap<Integer, Long> videoACKTime = new HashMap<>();
public HashMap<Integer, Integer> videoSizeSlot = new HashMap<>();
public HashMap<Integer, Integer> videoQualitySlot = new HashMap<>();
public ArrayList<Integer> videoACKReport = new ArrayList<Integer>();
public ArrayList<Long> timeACKReport = new ArrayList<Long>();
// related to the rate control part
public int curQuality = 1;
public float estThroughput = 0; // unit: MB/s
public float aveQuality = 0;
public float varQuality = 0;
public float expFactor = 0.25f;
public int polyDegree = 5;
PolynomialCurveFitter fitter = PolynomialCurveFitter.create(polyDegree);
public WeightedObservedPoints obs = new WeightedObservedPoints();
public double[] delayFitParams = new double[polyDegree];
public long calDelayStartTime;
public long calDelayEndTime;
public Stats(){
clientNum = nextNum;
}
public void fitDelay(float rate, float newDelay) {
obs.add(rate, newDelay);
delayFitParams = fitter.fit(obs.toList());
}
public float predictDelay(float rate) {
double result = 0;
for(int i=0;i<polyDegree;i++) {
result += delayFitParams[i] * Math.pow(rate, i);
}
return (float) result;
}
}
public class Utils {
// locate the statistics for each client by IP
public static HashMap<String, Stats> clientStats = new HashMap<>();
}
public class JavaServer {
public static void main(String[] args) {
final int MovePort = 8848;
final int FuncPort = 8080;
final int RTSPPort = 8088;
ServerThread moveServerThread = new ServerThread("Move Server thread", MovePort, 1);
moveServerThread.start();
ServerThread funcServerThread = new ServerThread("ACK Server thread", FuncPort, 2);
funcServerThread.start();
ServerThread rtspServerThread = new ServerThread("RTSP Server thread", RTSPPort, 0);
rtspServerThread.start();
}
public static class ServerThread extends Thread {
private int PORT;
private int Type;
public ServerThread(String name, int port, int type){
super(name);
PORT = port;
Type = type; // 1, movement server; 2, ACK server
}
@Override
public void run(){
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
while (true) {
Socket socket = serverSocket.accept();
if (socket == null) {
System.out.println(Thread.currentThread().getName()+" accept socket failed.");
break;
}
System.out.println(Thread.currentThread().getName()+" Receive connection from: "+socket.getInetAddress());
// at the initialization, receive internal IP address from client
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String clientAddr = reader.readLine();
System.out.println(Thread.currentThread().getName()+" Receive IP from: "+clientAddr);
if (Type == 0) {
// start the RTSP thread
if (!Utils.clientStats.containsKey(clientAddr)) {
Utils.clientStats.put(clientAddr,new Stats());
Stats.nextNum++;
}
new RTPThread("RTP thread "+clientAddr,socket, Stats.nextNum, clientAddr, reader).start();
}
if (Type == 1) {
Utils.teacherAddr = clientAddr;
PredictThread predThread = new PredictThread("Prediction Thread",socket,reader);
predThread.start();
}
else if (Type == 2) {
// wait for the statistic object initialization of the client
while(!Utils.clientStats.containsKey(clientAddr)){
try{
Thread.sleep(1);
}
catch (InterruptedException e){
e.printStackTrace();
}
}
// start the functional thread
FuncThread funcThread = new FuncThread("Functionalthread "+clientAddr,socket,clientAddr,reader);
funcThread.start();
}
}
} catch (IOException ex) {
System.out.println(Thread.currentThread().getName()+" exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
}
//遍历
for (String IP : Utils.clientStats.keySet()) {
IPs[cnt] = IP;
Stats statistics = Utils.clientStats.get(IP);
bandwidth_clients[cnt] = statistics.estThroughput;
d_qualities[cnt] = 1;
v_qualities[cnt] = 1;
cnt++;
}
4.键位置存储自定义对象
HashMap的键位置如果存储的是自定义对象,需要重写hashCode 和 equals方法