执行Java代码以获得O(1)中的结果
我有一个网络服务,我可以从中获得时间和价格。我已将这些记录保存在ConcurrentHashMap中,因为它需要在多线程环境中支持时间戳(LocalDateTime)作为键,价格(BigDecimal)作为值。要求获得以下详细信息执行Java代码以获得O(1)中的结果,java,time-complexity,big-o,concurrenthashmap,Java,Time Complexity,Big O,Concurrenthashmap,我有一个网络服务,我可以从中获得时间和价格。我已将这些记录保存在ConcurrentHashMap中,因为它需要在多线程环境中支持时间戳(LocalDateTime)作为键,价格(BigDecimal)作为值。要求获得以下详细信息 过去90项记录中的总记录 过去90条记录中的平均记录 最近90个记录中的最低价格 过去90年最高价格记录 过去90年的总价格记录 过去90个记录中的平均价格 我已成功地通过下面所示的代码a达到要求 ConcurrentHashMap<LocalDateTime,
ConcurrentHashMap<LocalDateTime, BigDecimal> data = // my full records
int totalRecords = 0;
BigDecimal highestPrice = new BigDecimal(0.0);
BigDecimal lowestPrice = new BigDecimal(0.0);
BigDecimal totalPriceSum = new BigDecimal(0.0);
Instant currentTime = Instant.now();
Duration limit = Duration.ofSeconds(90);
for (LocalDateTime time : data.keySet()) {
Duration duration = Duration.between(currentTime , time);
Boolean matches = ( duration.compareTo(limit) < 0 );
if(matches)
{
BigDecimal recordPrice = data.get(time);
if(recordPrice.compareTo(lowestPrice) < 0) {
lowestPrice = recordPrice;
}
if(recordPrice.compareTo(lowestPrice) > 0) {
highestPrice = recordPrice;
}
totalPriceSum = totalPriceSum.add(recordPrice);
totalRecords++;
}
}
System.out.println("Total records in last 90 records: "+ totalRecords);
System.out.println("Average records in last 90 records: "+ (totalRecords/90)*100);
System.out.println("Lowest Price in last 90 records: "+ lowestPrice);
System.out.println("Highest Price in last 90 records: "+ highestPrice);
System.out.println("Total Price in last 90 records: "+ totalPriceSum);
System.out.println("Average Price in last 90 records: "+ (totalPriceSum.doubleValue()/90)*100);
ConcurrentHashMap数据=//我的完整记录
int totalRecords=0;
BigDecimal highestPrice=新的BigDecimal(0.0);
BigDecimal lowestPrice=新的BigDecimal(0.0);
BigDecimal totalPriceSum=新的BigDecimal(0.0);
Instant currentTime=Instant.now();
持续时间限制=持续时间秒(90);
for(LocalDateTime:data.keySet()){
持续时间=持续时间之间(currentTime,time);
布尔匹配=(duration.compareTo(limit)<0);
如果(匹配)
{
BigDecimal recordPrice=data.get(时间);
if(记录价格比(最低价格)<0){
最低价格=记录价格;
}
if(记录价格比(最低价格)>0){
最高价格=记录价格;
}
totalPriceSum=totalPriceSum.add(记录价格);
totalRecords++;
}
}
System.out.println(“最近90条记录中的总记录:“+totalRecords”);
System.out.println(“最近90条记录中的平均记录数:”+(totalRecords/90)*100);
System.out.println(“过去90条记录中的最低价格:“+最低价格”);
System.out.println(“过去90条记录中的最高价格:“+最高价格”);
System.out.println(“最近90条记录中的总价:“+totalPriceSum”);
System.out.println(“最近90条记录的平均价格:”+(totalPriceSum.doubleValue()/90)*100);
但是我的客户说这有一些性能问题,代码应该在O(1)中运行并给出
有谁能帮助我或建议我一个不同的方法来实现这一点。我是否应该使用集合来实现O(1)可能您拥有的记录比过去90秒的记录多得多。循环浏览所有这些内容,只过滤出你感兴趣的少数几个内容,这是你花费大部分时间的地方。你要么
注意:这永远不会是真正的O(1),因为您正在迭代一个可以改变大小的列表。通过对正在循环的集合进行排序,您应该仍然能够极大地提高性能。从注释中可以看出,下面是我关于计算要使用的确切密钥的一个示例。它仍然使用
LocalDateTime
(而不是nano的Long)作为键,但它被截断为秒。因此,最多需要收集90把钥匙
存在聚合PriceRequest
类,用于在同一秒内保存并发请求。(它不是完全线程安全的。)
public类最后90秒{
private Map priceRequests=new ConcurrentHashMap();
公共静态void main(字符串[]args)引发异常{
Last90Seconds应用程序=新的Last90Seconds();
app.simulatePriceRequests();//连续模拟价格请求的线程
对于(int i=0;i<10;i++){
睡眠(9000);
app.reportOnPriceRequests();
}
}
私有void simulatePriceRequests(){
新线程(newrequestforpricesimulator()).start();
}
私有void reportOnPriceRequests(){
long startNanos=System.nanoTime();
新建ReportSimulator().generateReport();
long elapsednos=System.nanoTime()-startNanos;
System.out.println(“生成报告的时间为“+elapsednos/1000.0+”毫秒。\n\n”);
}
专用LocalDateTime截断秒(LocalDateTime ldt){
返回ldt.truncatedTo(计时单位秒);
}
private PriceRequest getPriceTracker(LocalDateTime密钥){
返回priceRequests.get(key);
}
private PriceRequest getPriceTrackerEvenIfAbsent(LocalDateTime密钥){
返回priceRequests.ComputeFabSent(键,v->new PriceRequest());
}
公共类RequestForPriceSimulator实现可运行{
@凌驾
公开募捐{
LocalDateTime rightNow=truncateToses(LocalDateTime.now());
LocalDateTime ninentySecondsFromNow=rightNow.plusSeconds(90);
while(rightNow.isBefore(nintentysecondsfromsnow)){
PriceRequest pt=getPriceTrackerEvenIfAbsent(立即发送);
double price=ThreadLocalRandom.current().nextDouble()*10.0;
pt.addRequest(价格);
试一试{
睡眠(10);
}捕捉(中断异常e){
e、 printStackTrace();
}
rightNow=truncateToses(LocalDateTime.now());
}
System.out.println(“全部完成模拟价格请求!\n”);
}
}
公共类报告模拟器{
公共无效生成器报告(){
双最低=双最大值;
最高加倍=最低加倍值;
双倍合计=0;
长请求计数器=0;
int键计数器=0;
int validKeyCounter=0;
LocalDateTime rightNow=truncateToses(LocalDateTime.now());
LocalDateTime key=rightNow.minsse
public class Last90Seconds {
private Map<LocalDateTime, PriceRequest> priceRequests = new ConcurrentHashMap<>();
public static void main(String[] args) throws Exception {
Last90Seconds app = new Last90Seconds();
app.simulatePriceRequests(); // thread which continuously simulates a price request
for (int i = 0; i < 10; i++) {
Thread.sleep(9000);
app.reportOnPriceRequests();
}
}
private void simulatePriceRequests() {
new Thread(new RequestForPriceSimulator()).start();
}
private void reportOnPriceRequests() {
long startNanos = System.nanoTime();
new ReportSimulator().generateReport();
long elapsedNanos = System.nanoTime() - startNanos;
System.out.println("Took " + elapsedNanos / 1000.0 + " milliseconds to generate report.\n\n");
}
private LocalDateTime truncateToSeconds(LocalDateTime ldt) {
return ldt.truncatedTo(ChronoUnit.SECONDS);
}
private PriceRequest getPriceTracker(LocalDateTime key) {
return priceRequests.get(key);
}
private PriceRequest getPriceTrackerEvenIfAbsent(LocalDateTime key) {
return priceRequests.computeIfAbsent(key, v -> new PriceRequest());
}
public class RequestForPriceSimulator implements Runnable {
@Override
public void run() {
LocalDateTime rightNow = truncateToSeconds(LocalDateTime.now());
LocalDateTime ninentySecondsFromNow = rightNow.plusSeconds(90);
while (rightNow.isBefore(ninentySecondsFromNow)) {
PriceRequest pt = getPriceTrackerEvenIfAbsent(rightNow);
double price = ThreadLocalRandom.current().nextDouble() * 10.0;
pt.addRequest(price);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
rightNow = truncateToSeconds(LocalDateTime.now());
}
System.out.println("All done simulating a price request!\n");
}
}
public class ReportSimulator {
public void generateReport() {
double lowest = Double.MAX_VALUE;
double highest = Double.MIN_VALUE;
double total = 0;
long requestCounter = 0;
int keyCounter = 0;
int validKeyCounter = 0;
LocalDateTime rightNow = truncateToSeconds(LocalDateTime.now());
LocalDateTime key = rightNow.minusSeconds(90);
while (key.isBefore(rightNow)) {
keyCounter++;
key = key.plusSeconds(1);
PriceRequest pt = getPriceTracker(key);
if (pt == null) {
continue;
}
validKeyCounter++;
if (pt.getLowest() < lowest) {
lowest = pt.getLowest();
}
if (pt.getHighest() < highest) {
highest = pt.getHighest();
}
total += pt.getTotal();
requestCounter += pt.getCounter();
}
System.out.println("Used " + validKeyCounter + " keys out of " + keyCounter + " possible keys.");
System.out.println("Total records in last 90 seconds: " + requestCounter);
System.out.println("Average records per second in last 90 seconds: " + requestCounter / 90);
System.out.println("Lowest Price in last 90 seconds: " + lowest);
System.out.println("Highest Price in last 90 seconds: " + highest);
System.out.println("Total Price in last 90 seconds: " + total);
System.out.println("Average Price in last 90 seconds: " + (total / requestCounter));
}
}
public class PriceRequest {
private long counter;
private double lowest;
private double highest;
private double total;
public PriceRequest() {
lowest = Double.MAX_VALUE;
highest = Double.MIN_VALUE;
}
public void addRequest(double price) {
synchronized (this) {
if (price < lowest) {
lowest = price;
}
if (price > highest) {
highest = price;
}
total += price;
counter++;
}
}
public double getCounter() {
synchronized (this) {
return counter;
}
}
public double getLowest() {
synchronized (this) {
return lowest;
}
}
public double getHighest() {
synchronized (this) {
return highest;
}
}
public double getTotal() {
synchronized (this) {
return total;
}
}
}
}