Table of contents
Low-level design (LLD) for Twitter:
User accounts and authentication: Twitter will need to allow users to create accounts, log in, and log out. We will also need to implement measures to ensure the security of user accounts, such as password hashing and potentially two-factor authentication.
Tweet creation and posting: Twitter will need to allow users to create and post tweets, which will involve creating forms and handling the associated server-side logic to process the input and store the tweets in a database.
User profiles and followers: Twitter will need to store information about users, such as their username, display name, and bio, as well as allow users to follow and be followed by other users. This will likely involve creating tables or data structures to store this information and implementing the necessary logic to manage the relationships between users.
Timeline and feed: Twitter will need to display a timeline or feed of tweets to each user, which will involve querying the database for the relevant tweets and displaying them to the user.
Search and hashtags: Twitter will need to allow users to search for tweets and users, as well as support hashtags to allow users to discover tweets about specific topics. This will involve implementing search functionality and handling any interactions with the server-side logic.
User interface: Finally, Twitter will need to design the user interface for the service, including the layout, navigation, and any necessary graphics or styling. This will involve creating wireframes and mockups, as well as implementing the front-end code to bring the design to life.
Code
import java.time.LocalDateTime;
import java.util.*;
// Core Twitter-like class
public class Twitter {
private Map<String, User> users;
private Map<Long, Tweet> tweets;
private Map<String, List<Notification>> notifications;
private CacheService cacheService; // Cache for faster access
private RateLimiter rateLimiter; // Rate limiter for actions
public Twitter() {
this.users = new HashMap<>();
this.tweets = new HashMap<>();
this.notifications = new HashMap<>();
this.cacheService = new CacheService();
this.rateLimiter = new RateLimiter();
}
// Enhanced: Create user with rate limiting
public void createUser(String name, String username, String profilePictureUrl) {
if (users.containsKey(username)) {
throw new IllegalArgumentException("Username already exists");
}
User user = new User(name, username, profilePictureUrl);
users.put(username, user);
}
// Enhanced: Real-time notifications on follow
public void followUser(String followerUsername, String followeeUsername) {
if (rateLimiter.isRateLimited(followerUsername, "follow")) {
throw new IllegalArgumentException("Follow action rate-limited");
}
User follower = users.get(followerUsername);
User followee = users.get(followeeUsername);
follower.follow(followee);
followee.addFollower(follower);
notifyUser(followee, follower.getUsername() + " started following you.", NotificationType.FOLLOW);
}
// Enhanced: Add tweet with hashtag and mentions processing
public void createTweet(String username, String text) {
User user = users.get(username);
if (rateLimiter.isRateLimited(username, "tweet")) {
throw new IllegalArgumentException("Tweet action rate-limited");
}
Tweet tweet = new Tweet(user, text, LocalDateTime.now());
tweets.put(tweet.getId(), tweet);
user.addTweet(tweet);
// Hashtag and mentions processing
processHashtagsAndMentions(tweet, text);
notifyFollowers(tweet);
}
// Enhanced: Comment with @mention notifications
public void commentOnTweet(String username, long tweetId, String text) {
User user = users.get(username);
Tweet tweet = tweets.get(tweetId);
Comment comment = new Comment(user, tweet, text, LocalDateTime.now());
tweet.addComment(comment);
user.addCommentedTweet(tweet);
notifyUser(tweet.getUser(), tweet.getUser().getUsername() + " commented on your tweet.", NotificationType.COMMENT);
processMentions(comment, text);
}
// Enhanced: Tweet search with caching
public List<Tweet> searchTweets(String query) {
return cacheService.searchCachedTweets(query); // Optimized with cache
}
// Enhanced: Real-time notification of likes
public void likeTweet(String username, long tweetId) {
User user = users.get(username);
Tweet tweet = tweets.get(tweetId);
tweet.addLike(user);
user.addLikedTweet(tweet);
notifyUser(tweet.getUser(), tweet.getUser().getUsername() + " liked your tweet.", NotificationType.LIKE);
}
// Enhanced: Trending hashtags with data caching
public List<String> getTrendingHashtags() {
return cacheService.getTrendingHashtags(); // Cached trending hashtags
}
// Notify followers in real-time about new tweet
private void notifyFollowers(Tweet tweet) {
User user = tweet.getUser();
for (User follower : user.getFollowers()) {
notifyUser(follower, tweet.getUser().getUsername() + " just tweeted.", NotificationType.TWEET);
}
}
// Notify individual user
private void notifyUser(User user, String message, NotificationType type) {
List<Notification> userNotifications = notifications.getOrDefault(user.getUsername(), new ArrayList<>());
Notification notification = new Notification(user, message, LocalDateTime.now());
userNotifications.add(notification);
notifications.put(user.getUsername(), userNotifications);
user.addNotification(notification);
}
// Enhanced: Handle hashtags and mentions
private void processHashtagsAndMentions(Tweet tweet, String text) {
List<String> hashtags = HashtagService.extractHashtags(text);
cacheService.cacheHashtags(hashtags);
List<String> mentions = MentionService.extractMentions(text);
for (String mention : mentions) {
User mentionedUser = users.get(mention);
if (mentionedUser != null) {
notifyUser(mentionedUser, "You were mentioned in a tweet.", NotificationType.MENTION);
}
}
}
// Handle mentions in comments
private void processMentions(Comment comment, String text) {
List<String> mentions = MentionService.extractMentions(text);
for (String mention : mentions) {
User mentionedUser = users.get(mention);
if (mentionedUser != null) {
notifyUser(mentionedUser, "You were mentioned in a comment.", NotificationType.MENTION);
}
}
}
}
// Enhanced Tweet with support for multiple media types
public class Tweet {
private long id;
private User user;
private String text;
private LocalDateTime createdAt;
private Set<User> likes;
private List<Comment> comments;
private List<Media> media;
public Tweet(User user, String text, LocalDateTime createdAt) {
this.id = IdGenerator.generateId();
this.user = user;
this.text = text;
this.createdAt = createdAt;
this.likes = new HashSet<>();
this.comments = new ArrayList<>();
this.media = new ArrayList<>();
}
public void addLike(User user) {
likes.add(user);
}
public void addComment(Comment comment) {
comments.add(comment);
}
public void addMedia(Media mediaFile) {
media.add(mediaFile);
}
// Getter methods...
}
// Enhanced Notification with real-time and push notifications
public class Notification {
private long id;
private User user;
private String message;
private LocalDateTime createdAt;
private boolean read;
public Notification(User user, String message, LocalDateTime createdAt) {
this.id = IdGenerator.generateId();
this.user = user;
this.message = message;
this.createdAt = createdAt;
this.read = false;
}
public void markAsRead() {
this.read = true;
}
// Getter methods...
}
// CacheService for caching popular tweets, hashtags, etc.
public class CacheService {
private Map<String, List<Tweet>> cachedTweets;
private Map<String, Integer> trendingHashtags;
public CacheService() {
this.cachedTweets = new HashMap<>();
this.trendingHashtags = new HashMap<>();
}
public List<Tweet> searchCachedTweets(String query) {
return cachedTweets.getOrDefault(query, new ArrayList<>());
}
public void cacheHashtags(List<String> hashtags) {
for (String hashtag : hashtags) {
trendingHashtags.put(hashtag, trendingHashtags.getOrDefault(hashtag, 0) + 1);
}
}
public List<String> getTrendingHashtags() {
return trendingHashtags.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.map(Map.Entry::getKey)
.limit(10)
.toList();
}
}
// RateLimiter to prevent abuse
public class RateLimiter {
private Map<String, Map<String, Long>> userActions;
public RateLimiter() {
userActions = new HashMap<>();
}
public boolean isRateLimited(String username, String action) {
Map<String, Long> actions = userActions.getOrDefault(username, new HashMap<>());
long currentTime = System.currentTimeMillis();
if (actions.containsKey(action) && currentTime - actions.get(action) < 10000) {
return true; // Rate-limited for 10 seconds between actions
}
actions.put(action, currentTime);
userActions.put(username, actions);
return false;
}
}