java - 一道优化的小代码题目, 面试题
巴扎黑
巴扎黑 2017-04-18 09:57:04
0
9
864

问题:

  1. Snack类的isExpired方法实现了什么功能?

  2. 现有相当大量的snack对象(如一个长度100万的Snack对象数组)需要执行isExpired方法,执行时候发现效率低下, 请分析原因, 并给出优化方案?

为了方便交流学习, 我把完整的题目都贴出来了, 我主要的问题是第二问, 大家有没有好的办法?

代码如下:

public class Snack { 
    
    public Snack(String name, Date expirDate){ 
        this.name = name;
        this.expireDate = expireDate;
    }
    
    private String name;
    private Date expireDate;
    
    public boolean isExpired(){
        Date now = new Date();
        return now.compareTo(this.expireDate) > 0 ;
    }

}
巴扎黑
巴扎黑

모든 응답(9)
Peter_Zhu

초대해주셔서 감사합니다.

  1. 바이두에서 확인하실 수 있습니다. 현재 날짜가 객체의 만료 날짜보다 이후인 경우 true를 반환합니다.

  2. 내 알고리즘이 매우 정확하지 않습니다. 오류가 있으면 댓글을 달아주세요. 먼저 개체의 만료 날짜가 올바른지 확인하세요. Orderly는 이진 검색 아이디어를 통해 배울 수 있습니다. 예를 들어 작은 것부터 큰 것까지 개체를 찾을 수 있으면 모든 후속 개체가 true를 반환합니다.

小葫芦

먼저 Date 객체의 compareTo 메서드 내부 구현을 살펴보면 오버헤드가 증가하는 clone 작업이 있습니다.

1. isExpired 메소드의 기능은 현재 객체가 만료되었는지 확인하는 것입니다. expireDate이 현재 서버 시간보다 이전이면 만료되지 않은 것으로 간주됩니다.

현재 isExpired 메소드를 실행해야 하는 스낵 객체(예: 길이가 1백만인 Snack 객체 배열)가 꽤 많습니다.

2. 이 표현은 다소 모호하므로 두 가지 상황으로 설명하겠습니다.
2.1 길이가 100W인 Snack 배열에서 isExpired 메서드를 순회하고 실행하면 JVM을 검사할 수 있습니다. 메모리 관리 및 가비지 수집 메커니즘은 프로그램이 직렬로 이러한 100만 개 개체의 isExpired 메서드를 실행하고(이러한 개체 생성 비용을 무시한다고 가정) 실행될 때마다 새로운 Date 객체가 생성되고 compareTo내부적으로 this.expireDate이 복제되므로 오버헤드가 상대적으로 커집니다.
2.2 일정 시간 내에 Snack 객체가 많이 발생합니다. 🎜> 메서드를 병렬로 실행하여 에 초점을 맞춥니다. 테스트는 높은 동시성 처리에 관한 것일 수도 있습니다. 2.1의 지식 포인트도 터치하면 추가 점수를 얻을 수 있습니다. isExpired개인적으로는 2.2의 확률이 더 높다고 생각합니다.

이 코드에 대한 나의 최적화 이해에 대해 이야기해 보세요.

1.

2.1
인 경우 long 또는 int(정확도 요구 사항이 높지 않은 경우)을 사용하여 저장합니다. 그런 다음 메서드 외부에 expireDate를 쌓을 수 있으며(시간 정확도 요구 사항이 그리 높지 않다고 가정) 메서드 내에서는 Date now = new Date()의 값만 비교하면 됩니다. isExperied2.2 now.getTime()이고 애플리케이션이 클러스터 환경에 배포되면 expireDate에서 객체를 생성할 수 없습니다. 예를 들어 서버 간 시간 동기화가 있어도 시간 불일치가 발생할 수 있기 때문입니다. , 기계 A 그리고 기계 B와 기계 B의 차이가 1초일 수도 있습니다. 이때 전역 시간 생성기를 사용할 수 있으며, 애플리케이션은 이 생성기를 호출하여 비교를 위한 현재 서버 시간을 가져옵니다.2. 비즈니스 관점에서 isExpired만료 시간Date의 정확성을 확인합니다. , 즉 [연도 | 월|일|시|분|초|밀리초]?, 다양한 정밀도의 저장 및 비교 전략도 다를 수 있습니다. 정밀도가 높을수록 비용도 높아집니다.
글이 좀 지저분하네요.

伊谢尔伦

데이터 양이 많은 경우 isExpired()에서 하나하나 시간을 구하려면 시간이 많이 걸립니다.
배열에 있는 각 객체의 isExpired()이 동시에 순차적으로 호출되므로 비교가 동시에 수행된다고 가정할 수 있으며, isExpired()에 오버로드

를 추가합니다. 으아악

전화할 때 할 수 있습니다

으아악
小葫芦

System.currentTimeMillis()

와 시간 비교
Peter_Zhu

으아악

小葫芦

배열을 우선 순위 대기열로 변경하세요. 힙의 최상위 요소에서만 isExpired()를 실행해야 할 때마다 성능이 O(n)에서 O(1)로 향상됩니다.

Peter_Zhu

이제 병렬이 보이니까 Java 8의 새로운 API인 병렬흐름을 써보고 싶어서 ㅎㅎ 그냥 참고용으로만 연습해봤습니다

  1. Date의 기존 CompareTo 메서드를 사용하여 비교

  2. Date의 System.currentTimeMillis() > expiredDate.getTime() 메소드를 사용하여 비교

각 비교 방법은 비교를 용이하게 하기 위해 5번 실행되는 동시에 각 방법은 3가지 모드를 사용하여 실행됩니다.

  1. for 루프 실행 모드

  2. 스트림 루프 실행 모드

  3. 병렬 스트림 루프 실행 모드

코드는 다음과 유사합니다.

으아악

최종 실행 결과는 다음과 같습니다.
100만 레벨

][2]

1000w급

요약하자면, 테스트 코드로 판단하면 시간 비교 방법을 변경해야 한다고 생각합니다(특정 실제 환경과 관련이 있을 수도 있음). flow 방식을 사용하면 실행 효율성이 실제로 향상됩니다. 다수의 배열이나 컬렉션을 운영할 때는 JDK가 특정 환경에 따라 더 나은 동시성 모드를 결정합니다.

迷茫

두 가지 최적화 포인트가 있습니다
1: Date 객체 생성
2. CompareTo() 메서드

大家讲道理

질문에서는 "현재 isExpired 메소드를 실행해야 하는 스낵 객체(길이가 100만 개의 스낵 객체 배열 등)가 많아 효율성이 낮은 것으로 나타났다"고 합니다. 실행 중"

여기에는 두 가지 핵심 문제가 있는데 어떤 문제를 해결해야 할지 모르겠습니다.

  1. 많은 수의 문제를 해결하려고 하시나요?
    2. 실행의 비효율성을 해결합니다.

질문 1,
10,000개의 객체 배열을 지웁니다. 할 일이 그다지 많지 않습니다.

질문 2,
isExpire() 메서드에서 실행된 코드를 삭제하세요. 이 메서드는 아무 작업도 수행하지 않으며 실행 효율성이 높아집니다.

최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿