Fix Docker Suddenly Not Working on Mac

Published: August 26, 2025  |  Categories: Docker, Mac, Troubleshooting

Warning: Some steps below will delete all your Docker containers and their data. Back up anything important before proceeding.

Docker Desktop on macOS can suddenly stop launching, freeze on startup, or become completely unresponsive — often after an OS update, a system crash, or a period of heavy use. This guide covers the most common causes and walks through a systematic fix from least destructive to most destructive.


How Docker Works on Mac (Background)

Unlike Linux, macOS doesn't have a native Linux kernel. Docker Desktop on Mac runs a lightweight Linux virtual machine (VM) under the hood using Apple's Hypervisor framework. All your containers run inside that VM.

This architecture means there are more moving parts that can break:

  • The VM itself might fail to start
  • The socket Docker clients talk to might not be created
  • File-sharing mounts between macOS and the VM might go stale
  • The Docker daemon inside the VM might crash

Understanding this helps you diagnose which layer is broken.


Prerequisites

  • macOS with Docker Desktop installed
  • Terminal access
  • Admin (sudo) privileges

Quick Checks First

Before doing anything destructive, try these fast checks:

Check if Docker daemon is actually running:

docker info

If you get Cannot connect to the Docker daemon — the daemon isn't running. If you get output, Docker is alive and the issue is elsewhere.

Check Docker Desktop logs:

tail -100 ~/Library/Containers/com.docker.docker/Data/log/vm/dockerd.log

Look for obvious error messages. This often tells you exactly what's wrong.

Check available disk space:

df -h ~

Docker's VM needs free space to operate. Less than 2 GB free can cause startup failures.


Step 1: Force Quit Docker

If Docker Desktop is frozen and won't quit normally:

  1. Open Activity Monitor (Applications > Utilities > Activity Monitor)
  2. Search for Docker
  3. Select Docker Desktop and click the Force Quit (X) button

Alternatively, from the terminal:

pkill -f Docker

Wait 5–10 seconds after killing it before trying to relaunch.


Step 2: Restart Docker Normally First

Before wiping anything, try a clean restart:

open -a Docker

Wait up to 2 minutes. If the whale icon in the menu bar stops animating and turns solid, Docker started successfully. Run docker ps to confirm. If it's still stuck after 2 minutes, proceed to the next steps.


Step 3: Remove Docker Container Files

This removes corrupted container data and resets Docker's internal state.

sudo rm -rf ~/Library/Containers/com.docker.*
What this does: Deletes all Docker container storage under your user library. This is irreversible — all stopped and running containers, their volumes, and their internal state will be gone after this step.

Step 4: Clear File Sharing Directories in Docker Settings

Docker's settings file sometimes references directories that no longer exist. This causes the VM to hang during startup as it tries to mount unavailable paths.

Open the settings file:

sudo nano ~/Library/Group\ Containers/group.com.docker/settings.json

Find the "filesharingDirectories" key and clear its array:

"filesharingDirectories": []

Save the file (Ctrl+O, then Enter) and exit (Ctrl+X). You can re-add your desired shared directories from Docker Desktop's Settings > Resources > File Sharing after it starts.


Step 5: Restart Docker and Verify

Launch Docker Desktop from your Applications folder. The first startup after a reset can take 60–90 seconds. Once Docker is running, verify it works:

docker run hello-world

You should see a "Hello from Docker!" message confirming everything is working.


Step 6: Full Uninstall and Reinstall (Last Resort)

If Docker still won't start, do a complete clean uninstall. If Docker Desktop won't open at all, remove it manually:

# Remove the app
sudo rm -rf /Applications/Docker.app

# Remove all data and config
rm -rf ~/Library/Group\ Containers/group.com.docker
rm -rf ~/Library/Containers/com.docker.docker
rm -rf ~/.docker
sudo rm -f /usr/local/bin/docker
sudo rm -f /usr/local/bin/docker-compose

Then download and reinstall the latest Docker Desktop from docker.com.


Why Does This Happen?

CauseWhat Breaks
macOS updateHypervisor permissions, kernel extensions
Abrupt shutdown / crashDocker's internal database gets corrupted
Renamed/deleted directoriesFile-sharing paths in settings become stale
Disk space fullVM can't write to its virtual disk
Docker Desktop auto-updatePartial update leaves inconsistent state
VPN software conflictVPN changes network interfaces Docker relies on

Common Error Messages and What They Mean

dial unix docker.raw.sock: connect: no such file or directory
→ Docker daemon is not running. Restart Docker Desktop.

Error response from daemon: OCI runtime create failed
→ Usually a permissions or disk space issue. Check df -h.

docker: command not found
→ Docker CLI is not in your PATH after reinstall. Restart your terminal or run export PATH=$PATH:/usr/local/bin.


Alternative: Use Colima Instead

If Docker Desktop keeps giving you trouble on Mac, consider Colima — a lightweight, open-source container runtime for macOS. It uses the same Docker CLI but without Docker Desktop's overhead:

brew install colima docker
colima start
docker run hello-world

Colima is free, uses less RAM, and starts faster than Docker Desktop for most development workflows.


References

Best Resources to Learn System Design

```

Published: December 9, 2024  |  Updated: July 17, 2026  |  Category: System Design

System design is one of the most important—and often most intimidating— skills for software engineers. Unlike algorithm problems, system design questions rarely have one correct answer.

The goal is to learn how to reason about trade-offs: scalability versus consistency, latency versus throughput, availability versus correctness, and simplicity versus flexibility.

This guide curates some of the best free and paid system design resources to help you move from beginner fundamentals to interview preparation and real-world production architecture.

```

Quick Resource Comparison

```

Use this table to quickly identify the resource that best matches your learning style and current experience level.

Resource Format Level Cost Best For
System Design Primer GitHub guide Beginner Free Building foundational knowledge
Roadmap.sh Interactive roadmap Beginner Free Structured learning progression
High Scalability Architecture blog Intermediate Free Real-world architecture case studies
Gaurav Sen YouTube videos Beginner–Intermediate Free Visual explanations and interview concepts
Hussein Nasser YouTube videos Intermediate–Advanced Free Backend and infrastructure internals
ByteByteGo Books and course Intermediate Free and paid System design interview preparation
Hello Interview Interactive platform Intermediate Free and paid Practice and interview simulation
Designing Data-Intensive Applications Book Advanced Paid Deep distributed-systems knowledge
```

What Is System Design?

```

System design is the process of defining the architecture, components, interfaces, data models, and data flow of a software system.

In a system design interview, you may be asked to design applications such as:

  • Design Twitter or X
  • Design a URL shortener like Bitly
  • Design WhatsApp
  • Design YouTube
  • Design Uber
  • Design a distributed key-value store
  • Design a notification service
  • Design a cloud file-storage platform

The interviewer is not necessarily looking for a perfect architecture. They want to understand how you:

  • Clarify functional and non-functional requirements
  • Estimate traffic, storage, and bandwidth
  • Break a large problem into manageable components
  • Select appropriate databases and infrastructure
  • Identify bottlenecks and failure scenarios
  • Explain and defend architectural trade-offs

These same skills are valuable outside interviews. They help engineers build systems that remain reliable, scalable, secure, and maintainable as usage grows.

```

Core System Design Topics to Master

```
Topic Key Concepts
Scalability Horizontal scaling, vertical scaling, load balancing, sharding, partitioning, and stateless services
Reliability Fault tolerance, replication, redundancy, high availability, failover, disaster recovery, SLAs, SLOs, and SLIs
Data Storage SQL versus NoSQL, indexing, normalization, denormalization, replication, partitioning, and data modeling
Distributed Systems CAP theorem, ACID, BASE, eventual consistency, consensus, distributed transactions, Raft, and Paxos
Performance Latency, throughput, bottlenecks, connection pooling, batching, compression, and backpressure
Networking DNS, TCP, UDP, HTTP, HTTPS, REST, GraphQL, gRPC, WebSockets, server-sent events, and long polling
Caching Browser caching, CDN caching, application caching, database caching, eviction policies, cache invalidation, and Redis
Messaging Message queues, Kafka, RabbitMQ, pub/sub, event streaming, delivery guarantees, retries, and dead-letter queues
API Architecture API gateways, rate limiting, pagination, versioning, idempotency, authentication, and service-to-service communication
Security Authentication, authorization, OAuth 2.0, OpenID Connect, encryption, secrets management, TLS, and zero-trust principles
Observability Logging, metrics, tracing, alerting, dashboards, correlation IDs, and incident investigation
Infrastructure Containers, Kubernetes, service discovery, reverse proxies, autoscaling, object storage, CDNs, and cloud architecture
Design Patterns CQRS, event sourcing, saga pattern, circuit breaker, bulkhead pattern, outbox pattern, and service mesh
```

Free System Design Resources

```

1. System Design Primer — GitHub

The System Design Primer by Donne Martin is one of the most popular open-source system design resources. It covers essential concepts such as DNS, CDNs, load balancers, database replication, caching, availability, consistency, and scalability.

It also includes sample designs for systems such as Twitter, web crawlers, paste services, and social-network data feeds.

Best for: Beginners building a strong foundation

2. Roadmap.sh — System Design Roadmap

Roadmap.sh provides a visual learning path that organizes system design topics into a logical progression. Each topic links to additional articles, videos, and learning materials.

It is especially useful when you are unsure which topic to study next or want to track your progress.

Best for: Structured progression and identifying knowledge gaps

3. High Scalability

High Scalability publishes architecture breakdowns and case studies describing how major technology companies build and scale their platforms.

Studying real-world systems helps you understand why engineering teams choose particular databases, caching layers, messaging platforms, and scaling strategies.

Best for: Learning from real-world architecture decisions

4. System Design Daily

System Design Daily presents system design concepts in short, approachable lessons. Quiz-style modules can help reinforce concepts through active recall.

Best for: Self-testing and daily practice

5. Gaurav Sen on YouTube

Gaurav Sen explains classic system design and distributed-systems topics using approachable whiteboard-style diagrams.

His content includes consistent hashing, distributed databases, load balancing, caching, messaging systems, and common interview problems.

Best for: Visual learners and interview fundamentals

6. Hussein Nasser on YouTube

Hussein Nasser produces detailed backend-engineering content covering database internals, networking, proxies, connection pooling, Postgres, Nginx, Kafka, gRPC, and other infrastructure components.

His videos are particularly useful for understanding how technologies behave beneath the abstraction layer.

Best for: Engineers seeking practical, lower-level depth

```

Engineering Blogs Worth Reading

```

Engineering blogs are among the best resources for learning how large production systems evolve. They explain real constraints, outages, migrations, trade-offs, and scaling decisions.

  • Netflix Technology Blog — Streaming architecture, reliability, resilience, data platforms, and cloud infrastructure
  • Uber Engineering — Geospatial systems, marketplace architecture, real-time data, observability, and microservices
  • Cloudflare Blog — Networking, security, CDNs, distributed systems, databases, and internet infrastructure
  • Stripe Engineering — Payments, APIs, database migrations, reliability, and developer infrastructure
  • Airbnb Engineering — Search, data infrastructure, experimentation, service architecture, and frontend platforms
  • Discord Engineering — Messaging systems, real-time communication, storage, and database scaling
  • Shopify Engineering — High-traffic commerce systems, databases, Ruby infrastructure, and reliability
  • LinkedIn Engineering — Kafka, data platforms, recommendation systems, search, and distributed infrastructure

Practice tip: After reading an engineering article, summarize the original problem, the previous architecture, the chosen solution, its disadvantages, and the measurable outcome.

```

Paid and Premium Resources

```

7. ByteByteGo — Alex Xu

ByteByteGo is based on Alex Xu's popular System Design Interview books. The platform is known for clear, polished diagrams and concise explanations of common architecture patterns.

It covers interview questions, databases, caching, messaging systems, distributed components, and real-world architecture examples.

Best for: Interview preparation and visual learning

8. Hello Interview

Hello Interview provides structured system design walkthroughs, interview rubrics, practice questions, and mock-interview preparation.

Its structured approach is useful for understanding what interviewers expect at different seniority levels.

Best for: Interview simulation and structured feedback

9. Grokking the System Design Interview

This course presents common system design problems in a structured, text-based format. It walks through requirements, architecture, components, storage, bottlenecks, and trade-offs.

The reading-oriented format can be faster to review than long video courses.

Best for: Structured problem sets and text-based learning

```

Best System Design Books

```

System Design Interview — An Insider's Guide

Author: Alex Xu

Volumes 1 and 2 are among the most widely recommended books for system design interview preparation. They contain clear diagrams, structured frameworks, estimation examples, and multiple interview-style design problems.

Best for: Practical interview preparation

Designing Data-Intensive Applications

Author: Martin Kleppmann

Often called DDIA, this book is one of the most important resources for understanding data systems. It covers storage engines, replication, partitioning, transactions, distributed systems, batch processing, and stream processing.

It is more detailed and theoretical than a typical interview-preparation book, but it builds the deep technical intuition expected from senior engineers and architects.

Best for: Deep distributed-systems understanding

```

Important Distributed-Systems Papers

```

Once you understand the fundamentals, reading influential engineering papers can help you see how major distributed technologies were designed.

  • The Google File System — Distributed storage for large-scale data-intensive applications
  • MapReduce — Distributed processing of large datasets
  • Bigtable — Google's distributed structured-storage system
  • Dynamo — Amazon's highly available key-value store
  • Spanner — Google's globally distributed relational database
  • Raft — An understandable consensus algorithm
  • Kafka — Distributed messaging and log-based data architecture

You do not need to memorize these papers. Focus on the problem each system was solving, the constraints involved, and the trade-offs made by its designers.

```

System Design Learning Roadmap

```
1

Internet and Networking Fundamentals

Learn DNS, TCP, HTTP, HTTPS, proxies, CDNs, latency, bandwidth, and client-server communication.

2

Databases and Data Modeling

Study relational databases, NoSQL databases, indexing, normalization, replication, and partitioning.

3

Caching and Content Delivery

Understand cache placement, eviction strategies, cache invalidation, Redis, and CDNs.

4

Load Balancing and Scalability

Learn horizontal scaling, stateless services, load-balancing algorithms, autoscaling, and traffic distribution.

5

Queues and Event-Driven Systems

Study message queues, pub/sub, Kafka, retries, idempotency, asynchronous processing, and delivery guarantees.

6

Distributed-Systems Concepts

Learn consistency models, CAP theorem, distributed transactions, consensus, leader election, and fault tolerance.

7

Observability and Reliability

Understand logging, metrics, tracing, alerting, SLOs, incident response, and disaster recovery.

8

Interview Practice

Practice complete system designs under time constraints and explain every architectural decision clearly.

```

Suggested Three-Month Learning Plan

```
Stage Duration Goal
Foundations Weeks 1–2 Learn networking, databases, caching, load balancing, and basic scalability concepts
Distributed Systems Weeks 3–5 Study replication, partitioning, consistency, messaging, and failure handling
Case Studies Weeks 6–8 Analyze real systems and identify recurring architecture patterns
Interview Practice Weeks 9–12 Complete timed system design questions and improve communication
Advanced Learning Ongoing Read DDIA, engineering blogs, architecture papers, and production incident reports

Weeks 1–2: Build the Foundation

Read the System Design Primer and study the main building blocks. Do not try to memorize complete architectures. Build vocabulary and understand what each component does.

Weeks 3–4: Identify Knowledge Gaps

Follow the Roadmap.sh system design path and watch targeted videos on weak areas such as consistent hashing, database replication, message queues, caching, or load balancing.

Weeks 5–8: Study Real Systems

Read two or three engineering case studies each week. For every case study, identify the requirements, original bottleneck, selected solution, and resulting trade-offs.

Weeks 9–12: Practice Interviews

Start solving complete design problems. Set a timer for 45 to 60 minutes and practice explaining your architecture out loud.

Ongoing: Develop Technical Depth

Read Designing Data-Intensive Applications, engineering blogs, distributed-systems papers, and production postmortems.

```

A Practical System Design Interview Flow

```

A structured process prevents you from jumping into architecture before understanding the problem.

  1. Clarify requirements

    Identify core features, users, constraints, expected scale, and what is outside the scope.

  2. Define non-functional requirements

    Discuss availability, consistency, latency, durability, security, and reliability expectations.

  3. Estimate scale

    Estimate daily active users, requests per second, read-to-write ratio, bandwidth, and storage growth.

  4. Define APIs and data models

    Identify major API operations and the core entities that must be stored.

  5. Draw the high-level architecture

    Show clients, load balancers, services, databases, caches, queues, and external dependencies.

  6. Deep-dive into critical components

    Spend time on the components that are most important or technically challenging.

  7. Identify bottlenecks and failures

    Discuss hot partitions, overloaded services, database failures, queue backlogs, cache failures, and network partitions.

  8. Scale and improve the design

    Introduce partitioning, replication, caching, asynchronous processing, autoscaling, and regional distribution where necessary.

  9. Summarize trade-offs

    Explain what the design optimizes for and what limitations still remain.

```

System Design Problems by Category

```

Social Media

  • Design Twitter or X
  • Design Instagram
  • Design a news feed
  • Design a social graph

Messaging

  • Design WhatsApp
  • Design Slack
  • Design Discord
  • Design a notification service

Video and Streaming

  • Design YouTube
  • Design Netflix
  • Design a live-streaming service
  • Design a video-processing pipeline

Storage

  • Design Dropbox
  • Design Google Drive
  • Design object storage
  • Design a distributed file system

Search

  • Design a search engine
  • Design autocomplete
  • Design a web crawler
  • Design log search

Location-Based Systems

  • Design Uber
  • Design Google Maps
  • Design nearby-place search
  • Design driver tracking

Commerce and Payments

  • Design an e-commerce platform
  • Design a payment system
  • Design inventory management
  • Design a ticket-booking platform

Infrastructure

  • Design a URL shortener
  • Design a rate limiter
  • Design a distributed cache
  • Design a key-value store
```

Common System Design Mistakes

```
  • Jumping into architecture immediately. Clarify the requirements and constraints before drawing components.
  • Memorizing complete solutions. Use reference designs to learn patterns, not scripts.
  • Ignoring scale estimates. Traffic and storage estimates influence nearly every design decision.
  • Choosing technology without justification. Explain why a relational database, NoSQL database, cache, queue, or search engine fits the requirements.
  • Designing only for the happy path. Consider retries, duplicate events, timeouts, partial failures, network partitions, and regional outages.
  • Forgetting data models and APIs. Architecture becomes vague when the main entities and operations are undefined.
  • Ignoring observability. Production systems require logging, metrics, tracing, dashboards, and alerts.
  • Not discussing security. Mention authentication, authorization, encryption, rate limiting, secrets, and abuse prevention.
  • Overengineering the first version. Start with a simple design and evolve it as scale and requirements increase.
  • Not communicating trade-offs. A good design is not just a diagram. It is a clearly explained set of engineering decisions.
```

How to Practice System Design Effectively

```

Design Systems Out Loud

Set a timer for 45 minutes and design a system from scratch. Use paper, a whiteboard, a diagramming tool, or a blank document.

Explain your reasoning out loud as though an interviewer were listening. Speaking forces you to make assumptions and trade-offs explicit.

Start With a Simple Design

Begin with a single service and a single database. Then identify the point at which the architecture stops meeting the requirements.

Add caching, replication, queues, partitioning, and additional services only when the design needs them.

Critique Existing Products

When using an application, think about how it may be built. For example:

  • How does Instagram generate a personalized feed?
  • How does Uber match drivers and passengers in real time?
  • How does YouTube process and distribute uploaded videos?
  • How does Slack deliver messages to multiple devices?
  • How does Amazon prevent overselling limited inventory?

Form a hypothesis and then compare it with engineering articles or public architecture discussions.

Practice Capacity Estimation

Estimation helps you choose appropriate storage, caching, networking, and partitioning strategies.

Practice estimating:

  • Requests per second
  • Read-to-write ratio
  • Storage required per day and per year
  • Bandwidth requirements
  • Cache size
  • Number of database partitions

Review Your Own Design

After completing a practice problem, ask:

  • What is the largest bottleneck?
  • Which component is a single point of failure?
  • What happens if the cache becomes unavailable?
  • What happens when messages are processed twice?
  • How would the system behave during a regional outage?
  • How would I monitor and debug this system?
  • What would I simplify for the first production version?
```

When Are You Ready for a System Design Interview?

```

You do not need to know every database or distributed-systems algorithm. You are ready to begin interviewing when you can:

  • Clarify requirements before proposing a solution
  • Estimate traffic and storage at a reasonable level
  • Draw a clear high-level architecture
  • Explain database, caching, and messaging choices
  • Discuss reliability and failure scenarios
  • Identify bottlenecks and scaling strategies
  • Explain the trade-offs behind your decisions
  • Complete a design discussion within 45 to 60 minutes

You do not have to produce a perfect architecture. You need to demonstrate organized thinking, sound fundamentals, and clear communication.

```

Final Thoughts

```

Every large-scale application is built from a familiar collection of components: servers, databases, caches, queues, object storage, search systems, networks, load balancers, and monitoring tools.

Great system designers do not memorize complete architectures. They understand these building blocks deeply and know how to combine them based on requirements, constraints, and trade-offs.

Start with the fundamentals, study real production systems, and practice explaining your decisions clearly. Over time, you will develop the technical intuition needed to design systems that are scalable, reliable, maintainable, and secure.

```

Cannot Import XGBoost in Jupyter Notebook

Published: October 16, 2024  |  Categories: Python, Jupyter, Machine Learning

XGBoost is one of the most widely used machine learning libraries — it's behind many winning Kaggle solutions and is a go-to for structured data problems. But it has a frustrating quirk: on some systems, especially macOS, it fails to import with a cryptic error about a missing runtime library. This post explains why it happens and how to fix it on every platform.


The Error

You'll see something like this when running import xgboost:

XGBoostError: XGBoost Library (libxgboost.dylib) could not be loaded.
Likely causes:
  * OpenMP runtime is not installed
    - vcomp140.dll or libgomp-1.dll for Windows
    - libomp.dylib for Mac OSX
    - libgomp.so for Linux and other UNIX-like OSes
  * You are running 32-bit Python on a 64-bit OS

Why This Happens

XGBoost uses OpenMP (Open Multi-Processing) to run computations in parallel across CPU cores. OpenMP is not part of Python or XGBoost itself — it's a separate shared library that XGBoost expects to find on the system at runtime.

The problem is that OpenMP isn't installed by default on:

  • Fresh macOS installs (Apple's Clang compiler doesn't bundle it)
  • New virtual environments (Python envs don't carry system libraries)
  • Minimal Linux containers (stripped-down Docker images often omit it)

When XGBoost starts and tries to load the OpenMP shared library, it can't find it — and fails with the error above.


Fix on macOS

Install the missing OpenMP runtime via Homebrew:

brew install libomp

If Homebrew isn't installed yet, run this first:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

After installing libomp, restart your Jupyter kernel — not just the cell, the whole kernel. Go to Kernel > Restart in the menu.

Why kernel restart matters: Python caches import failures in the current session. Even after installing the missing library, the import will keep failing until you start a fresh Python process. Rerunning the cell isn't enough — you must restart the kernel.

Then try importing again:

import xgboost as xgb
print(xgb.__version__)

Fix on Windows

On Windows the import error is caused by a missing Visual C++ runtime:

  1. Go to the Microsoft Visual C++ Redistributable page
  2. Download the x64 version (vc_redist.x64.exe)
  3. Install it and restart your machine
  4. Try importing XGBoost again

If that doesn't work, try reinstalling via pip:

pip uninstall xgboost
pip install xgboost

Fix on Linux

Install libgomp via your package manager:

# Ubuntu / Debian
sudo apt-get update && sudo apt-get install libgomp1

# CentOS / RHEL
sudo yum install libgomp

# Fedora
sudo dnf install libgomp

# Alpine (e.g. in Docker)
apk add libgomp

Check Which Python Jupyter Is Using

The most common hidden cause of this error is an environment mismatch: XGBoost is installed in one Python environment, but Jupyter is running from a different one.

Check which Python your Jupyter kernel is using:

import sys
print(sys.executable)

Then check if XGBoost is installed in that environment:

/path/to/your/python -c "import xgboost; print(xgboost.__version__)"

If XGBoost is installed but not in the path Jupyter is using, reinstall it in the correct environment:

/path/to/your/python -m pip install xgboost

Using Conda?

If you're using a conda environment, install XGBoost through conda rather than pip — conda resolves the native library dependencies automatically:

conda install -c conda-forge xgboost

Verifying the Fix

Once XGBoost imports successfully, run a quick sanity check:

import xgboost as xgb
import numpy as np

X = np.random.rand(100, 5)
y = np.random.randint(0, 2, 100)

model = xgb.XGBClassifier(n_estimators=10, eval_metric='logloss')
model.fit(X, y)
print("XGBoost is working correctly. Version:", xgb.__version__)

If this runs without errors, you're good to go.


Summary

PlatformRoot CauseFix
macOSMissing libomp.dylibbrew install libomp
WindowsMissing Visual C++ runtimeInstall VC++ Redistributable
LinuxMissing libgomp.sosudo apt-get install libgomp1
AnyEnvironment mismatchCheck sys.executable, reinstall in correct env
AnyStale import cacheRestart Jupyter kernel after installing

The fix is almost always a one-liner. The tricky part is knowing that you need to restart the kernel — not just re-run the cell — after making any changes.

If you've worked with Node.js, you've used npm. But npx trips people up — it looks similar, it ships with npm, yet it does something fundamentally different. This post explains the distinction clearly with practical examples.


npm — Node Package Manager

npm manages packages: installing, updating, removing, and tracking dependencies in your project.

npm install lodash          # install as a project dependency
npm install -g typescript   # install globally on your machine
npm uninstall lodash        # remove a package
npm update                  # update all packages
npm list                    # show installed packages and versions

When you run npm install, npm downloads packages into node_modules and records them in package.json. Those packages stay on your machine until you explicitly remove them.


npx — Node Package Executor

npx runs a package without installing it permanently. It temporarily fetches the package, executes it, then discards it.

npx create-react-app my-app

This runs create-react-app without you ever having to install it globally. Perfect for CLI tools you use occasionally.


Side-by-Side Comparison

npmnpx
PurposeManage packagesExecute packages
Installs to diskYesNo (temporary)
Good forLibraries your code importsCLI tools you run once
Stays after useYesNo
Examplenpm install expressnpx create-react-app

Practical Examples

Creating a React app

# With npx — no global install needed
npx create-react-app my-app

# With npm — requires a prior global install
npm install -g create-react-app
create-react-app my-app

The npx approach is cleaner and always runs the latest version of the tool.

Running a one-off script

# Run a linter without installing it in your project
npx eslint src/

# Generate types from an OpenAPI spec
npx openapi-typescript schema.yaml -o types.ts

Running a specific version

npx node@18 --version   # run a command with a specific Node version

When to Use Which

Use npm install when:

  • You're adding a library your code will import (express, lodash, react)
  • You're adding a dev tool that runs frequently (eslint, jest, typescript)

Use npx when:

  • You're using a scaffolding tool once (create-react-app, create-next-app)
  • You want to run the latest version without worrying about a stale global install
  • You're trying a package without committing to it

How npx Resolves Packages

npx doesn't blindly download from the internet every time. It follows a resolution order:

  1. Local node_modules/.bin — if the package is already installed in your project, npx runs it directly without downloading anything
  2. Global install — if the package is globally installed, npx uses that
  3. npm registry — only if neither of the above is found does npx download the package temporarily

This means npx jest in a project that has Jest installed will run your project's version of Jest — no download needed. npx isn't just a remote runner; it's a smart executor that prefers local installs.


npm Scripts as an Alternative

Your package.json can define custom scripts that run locally installed binaries directly, without needing npx:

// package.json
{
  "scripts": {
    "lint": "eslint src/",
    "format": "prettier --write .",
    "type-check": "tsc --noEmit"
  }
}

Run them with:

npm run lint
npm run format
npm run type-check

This is the preferred approach for tools that run frequently in a project (linters, formatters, test runners). The binaries live in node_modules/.bin, and npm knows to look there when executing scripts. You don't need to install ESLint globally or use npx for a project-local tool you run daily.


Keeping Global Installs Clean

Before npx, the common advice was to install project scaffolding tools globally:

npm install -g create-react-app
npm install -g @angular/cli
npm install -g vue-cli

This leads to several problems: global installs can go stale (you're running an old version), they pollute your system, and they can conflict between projects. npx solves all three — you always run the latest version, nothing persists, and there's no global state to manage.

As a rule: install globally only tools you genuinely use across all projects (like serve, http-server) and let npx handle everything else.


pnpm and pnpx

If you use pnpm as your package manager, the equivalent executor is pnpm dlx (formerly pnpx):

pnpm dlx create-react-app my-app    # equivalent to npx create-react-app
pnpm exec eslint src/               # run a locally installed package

The distinction between "run local" (exec) and "download and run" (dlx) is more explicit with pnpm than with npx, which handles both cases automatically.


Summary

npm and npx complement each other. npm is for managing the packages your project depends on long-term. npx is for running packages on the fly without the overhead of a global install. For tools you run repeatedly in a project, define them as npm run scripts instead — it's more explicit, version-pinned, and doesn't require npx at all.

The Hamming weight of a number is the count of bits set to 1 in its binary representation. It's also called the popcount (population count) or bit count. This concept comes up in coding interviews, error detection algorithms, and low-level programming.

  • 5 in binary is 101 → Hamming weight = 2
  • 8 in binary is 1000 → Hamming weight = 1
  • 255 in binary is 11111111 → Hamming weight = 8

Real-World Uses

  • Error detection/correction: Hamming codes use bit counts to detect and correct transmission errors
  • Cryptography: Many algorithms work with bit patterns and their weights
  • Feature similarity: Hamming distance measures similarity between binary feature vectors in ML
  • Chess engines: Bitboards represent piece positions; popcount tells you how many pieces are on the board

Three Approaches in Java

Method 1: Division and Remainder


 public static int hammingWeightDivision(int n) {
    int count = 0;
    while (n > 0) {
        if (n % 2 == 1) {
            count++;
        }
        n = n / 2;
    }
    return count;
}

How it works: Each division by 2 right-shifts the number by one bit. The remainder (n % 2) is 1 if the least significant bit was set. The loop ends when all bits are consumed (n reaches 0).

Limitation: Doesn't handle negative integers correctly — the loop exits at 0, missing the sign bit.


Method 2: Bit Masking


public static int hammingWeightBitMask(int n) {
    int count = 0;
    int mask = 1;
    for (int i = 0; i < 32; i++) {
        if ((n & mask) != 0) {
            count++;
        }
        mask <<= 1; // shift mask left by one position
    }
    return count;
}

How it works: The mask starts at 00000000...00000001 and shifts left by one bit each iteration, visiting all 32 positions. (n & mask) != 0 tells us whether that specific bit is set.

Advantage: Works correctly for all 32 bits including the sign bit — handles negative integers.


Method 3: Brian Kernighan's Algorithm (Most Elegant)

This technique exploits the fact that n & (n-1) always clears the lowest set bit of n:

public static int hammingWeightKernighan(int n) {
    int count = 0;
    while (n != 0) {
        n = n & (n - 1); // clears the lowest set bit
        count++;
    }
    return count;
}

Walkthrough for n = 12 (binary 1100):

n = 1100  →  n-1 = 1011  →  n & (n-1) = 1000  (count=1)
n = 1000  →  n-1 = 0111  →  n & (n-1) = 0000  (count=2)
n = 0  → loop exits

Why it's elegant: It only iterates as many times as there are set bits. If only 2 bits are set in a 64-bit number, it runs 2 iterations — not 64.


Complete Example

public class HammingWeight {

    public static int byDivision(int n) {
        int count = 0;
        while (n > 0) {
            if (n % 2 == 1) count++;
            n = n / 2;
        }
        return count;
    }

    public static int byBitMask(int n) {
        int count = 0;
        int mask = 1;
        for (int i = 0; i < 32; i++) {
            if ((n & mask) != 0) count++;
            mask <<= 1;
        }
        return count;
    }

    public static int byKernighan(int n) {
        int count = 0;
        while (n != 0) {
            n = n & (n - 1);
            count++;
        }
        return count;
    }

    public static void main(String[] args) {
        int[] tests = {0, 1, 5, 8, 15, 255};
        for (int val : tests) {
            System.out.printf("%-6d → bitMask=%-3d kernighan=%-3d builtin=%d%n",
                val, byBitMask(val), byKernighan(val), Integer.bitCount(val));
        }
    }
}

Output:

0      → bitMask=0   kernighan=0   builtin=0
1      → bitMask=1   kernighan=1   builtin=1
5      → bitMask=2   kernighan=2   builtin=2
8      → bitMask=1   kernighan=1   builtin=1
15     → bitMask=4   kernighan=4   builtin=4
255    → bitMask=8   kernighan=8   builtin=8

Built-in Java Method

Java provides Integer.bitCount() in java.lang — no import needed. It uses a hardware-level POPCNT instruction on modern CPUs and is significantly faster than any manual implementation:

System.out.println(Integer.bitCount(5));            // 2
System.out.println(Integer.bitCount(255));           // 8
System.out.println(Integer.bitCount(Integer.MAX_VALUE)); // 31
System.out.println(Long.bitCount(Long.MAX_VALUE));   // 63

For production code, always use Integer.bitCount(). The manual implementations are valuable for learning and interview contexts.


Comparing All Approaches

MethodTime ComplexityHandles NegativesNotes
Division & RemainderO(log n)NoMost readable; fails on negative ints
Bit MaskingO(32) = O(1)YesAlways 32 iterations
Brian KernighanO(popcount)PartialFastest when few bits set
Integer.bitCount()O(1)YesUses hardware instruction; use in production

Bonus: Hamming Distance

The Hamming distance between two integers is the number of bit positions where they differ. It's computed with XOR (which marks differing bits) followed by a popcount:

int hammingDistance(int x, int y) {
    return Integer.bitCount(x ^ y);
}

System.out.println(hammingDistance(1, 4));  // 0001 ^ 0100 = 0101 → 2
System.out.println(hammingDistance(3, 5));  // 011 ^ 101 = 110 → 2

OptionalInt is a container that may or may not hold an int value. It's Java's way of explicitly representing the possibility of "no result" without using null or throwing exceptions — avoiding NullPointerException at the source.

It's part of a family of optional types in Java 8+:

ClassWraps
OptionalIntint
OptionalLonglong
OptionalDoubledouble
Optional<T>Any object type

The primitive-specific versions (OptionalInt, OptionalLong, OptionalDouble) exist for performance — they avoid boxing to wrapper types like Integer.


Core Methods

MethodDescription
isPresent()Returns true if a value is present
getAsInt()Returns the value; throws NoSuchElementException if empty
orElse(int other)Returns the value if present, otherwise other
orElseGet(IntSupplier)Returns the value if present, otherwise calls the supplier
ifPresent(IntConsumer)Runs an action if a value is present

Basic Example

import java.util.Arrays;
import java.util.OptionalInt;

public class OptionalIntExample {

    public static void main(String[] args) {
        int[] numbers = {9, 10, 11, 12, 15, 25};

        // reduce() returns OptionalInt because the array could be empty
        OptionalInt first = Arrays.stream(numbers)
                                  .reduce((left, right) -> left);

        if (first.isPresent()) {
            System.out.println("First element: " + first.getAsInt()); // 9
        }
    }
}

Using orElse() and orElseGet()

orElse() is cleaner than an if/else block for providing a default:

int[] numbers = {9, 10, 11, 12};
int[] empty = {};

OptionalInt result = Arrays.stream(numbers).filter(n -> n > 20).findFirst();
System.out.println(result.orElse(-1)); // -1 (no element > 20)

OptionalInt maxVal = Arrays.stream(empty).max();
System.out.println(maxVal.orElse(0)); // 0 (stream was empty)

OptionalInt from Stream Operations

Many IntStream terminal operations return OptionalInt because the stream may be empty:

int[] data = {3, 7, 2, 9, 4};

OptionalInt max = Arrays.stream(data).max();
OptionalInt min = Arrays.stream(data).min();
OptionalInt any = Arrays.stream(data).filter(n -> n > 5).findAny();

max.ifPresent(v -> System.out.println("Max: " + v)); // Max: 9
min.ifPresent(v -> System.out.println("Min: " + v)); // Min: 2
any.ifPresent(v -> System.out.println("Found: " + v)); // Found: 7

OptionalInt vs Optional<Integer>

You might wonder why not just use Optional<Integer>. The difference is boxing:

// OptionalInt — no boxing, primitive int stored directly
OptionalInt a = OptionalInt.of(42);

// Optional<Integer> — boxes int to Integer object
Optional<Integer> b = Optional.of(42);

For stream operations on int arrays and IntStream, use OptionalInt. For collections of Integer objects, use Optional<Integer>. Prefer OptionalInt whenever you're working with primitives to avoid unnecessary heap allocation.


isEmpty() — Java 11+

Java 11 added isEmpty() as the logical complement of isPresent():

OptionalInt result = Arrays.stream(new int[]{}).max();

if (result.isEmpty()) {
    System.out.println("No values in stream"); // prints this
}

This is purely a readability improvement. result.isEmpty() is equivalent to !result.isPresent(). Use whichever reads more naturally in context — conditions like "if we got nothing, log a warning" read better with isEmpty().


stream() — Java 9+

OptionalInt.stream() returns an IntStream containing one value if present, or an empty stream if absent. This is useful for flatMapping:

int[] arrays = {3, 1, 4};

// Each OptionalInt gets converted to a 0-or-1-element stream
IntStream combined = Arrays.stream(arrays)
    .filter(n -> n > 2)
    .findFirst()
    .stream(); // either stream of [3] or empty stream

combined.forEach(System.out::println); // 3

Common Pitfall: Calling getAsInt() Without Checking

The most frequent mistake with OptionalInt is calling getAsInt() unconditionally:

// WRONG — throws NoSuchElementException if stream is empty
int max = Arrays.stream(new int[]{}).max().getAsInt();

// CORRECT — always provide a fallback
int max = Arrays.stream(new int[]{}).max().orElse(Integer.MIN_VALUE);

// ALSO CORRECT — check first
OptionalInt maxOpt = Arrays.stream(new int[]{}).max();
if (maxOpt.isPresent()) {
    System.out.println(maxOpt.getAsInt());
}

Only call getAsInt() when you have a guarantee the stream is non-empty, or after an isPresent() check.


When NOT to Use OptionalInt

While OptionalInt is useful as a method return type, avoid using it in these situations:

  • As a method parameter — callers should pass an int or use overloading; making callers wrap values in OptionalInt just to pass them is awkward
  • As an instance field — use null or a sentinel value for nullable fields; OptionalInt fields add memory overhead with little benefit
  • Inside collections — a List<OptionalInt> is almost always a design mistake; filter out missing values before collecting instead

OptionalInt is designed specifically for method return values where "no result" is a normal, expected outcome — like stream terminal operations on a potentially empty stream.


Summary

OptionalInt makes "no value" an explicit part of your API rather than something a caller has to guess at. Use orElse() for a concise default, isPresent() / isEmpty() for conditional logic, and avoid calling getAsInt() without a guard. Reserve it for method return values — not fields or parameters.

Bucket sort is a distribution-based sorting algorithm. Instead of comparing elements, it spreads them into "buckets" based on their value, sorts each bucket individually, then concatenates the results. When data is uniformly distributed, it achieves average O(n) time — faster than comparison-based sorts which are bounded by O(n log n).


How Bucket Sort Works

  1. Find the minimum and maximum values in the input
  2. Create k empty buckets covering the value range
  3. Distribute each element into its appropriate bucket
  4. Sort each bucket individually
  5. Concatenate all buckets in order to produce the sorted output

Visual Walkthrough

Input: [42, 13, 75, 29, 88, 5, 61, 37] — min=5, max=88, 4 buckets

Range per bucket = (88 - 5 + 1) / 4 ≈ 21

Bucket 0 [5–25]:   [13, 5]      → sorted: [5, 13]
Bucket 1 [26–46]:  [42, 29, 37] → sorted: [29, 37, 42]
Bucket 2 [47–67]:  [61]         → sorted: [61]
Bucket 3 [68–88]:  [75, 88]     → sorted: [75, 88]

Final result: [5, 13, 29, 37, 42, 61, 75, 88] ✓

Java Implementation

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class BucketSort {

    public static void bucketSort(int[] arr) {
        if (arr == null || arr.length <= 1) return;

        int min = arr[0], max = arr[0];
        for (int val : arr) {
            if (val < min) min = val;
            if (val > max) max = val;
        }

        if (min == max) return; // all values are equal

        int bucketCount = arr.length;
        List<List<Integer>> buckets = new ArrayList<>(bucketCount);
        for (int i = 0; i < bucketCount; i++) {
            buckets.add(new ArrayList<>());
        }

        double divisor = (double)(max - min + 1) / bucketCount;
        for (int val : arr) {
            int bucketIndex = (int)((val - min) / divisor);
            // Clamp to avoid floating-point edge cases
            if (bucketIndex >= bucketCount) bucketIndex = bucketCount - 1;
            buckets.get(bucketIndex).add(val);
        }

        int index = 0;
        for (List<Integer> bucket : buckets) {
            Collections.sort(bucket);
            for (int val : bucket) {
                arr[index++] = val;
            }
        }
    }

    public static void main(String[] args) {
        int[] data = {42, 13, 75, 29, 88, 5, 61, 37};

        System.out.print("Before: ");
        for (int v : data) System.out.print(v + " ");

        bucketSort(data);

        System.out.print("\nAfter:  ");
        for (int v : data) System.out.print(v + " ");
    }
}

Output:

Before: 42 13 75 29 88 5 61 37
After:  5 13 29 37 42 61 75 88

Floating-Point Variant

Bucket sort is classically defined for floating-point values in [0, 1):

public static void bucketSortFloat(double[] arr) {
    int n = arr.length;
    List<List<Double>> buckets = new ArrayList<>(n);
    for (int i = 0; i < n; i++) buckets.add(new ArrayList<>());

    for (double val : arr) {
        int index = (int)(val * n);
        if (index == n) index = n - 1;
        buckets.get(index).add(val);
    }

    int pos = 0;
    for (List<Double> bucket : buckets) {
        Collections.sort(bucket);
        for (double val : bucket) arr[pos++] = val;
    }
}

// Usage:
double[] data = {0.72, 0.17, 0.39, 0.55, 0.14, 0.81};
bucketSortFloat(data);
// Result: 0.14 0.17 0.39 0.55 0.72 0.81

Time and Space Complexity

CaseTimeNotes
BestO(n + k)Uniform distribution, ~1 element per bucket
AverageO(n + k)Uniformly distributed input
WorstO(n²)All elements in one bucket
SpaceO(n + k)n elements + k bucket lists

The worst case happens when input is highly skewed — all elements cluster in one bucket and the inner sort dominates.


When to Use Bucket Sort

Good fit:

  • Input values are uniformly distributed across a known finite range
  • Sorting floating-point numbers between 0 and 1
  • You need average O(n) performance and can afford O(n + k) extra memory

Poor fit:

  • Input is skewed (bucket sort degrades to O(n²))
  • The value range is unknown or extremely large
  • Memory is constrained
  • You need a guaranteed worst-case bound — use merge sort instead

Bucket Sort vs. Other Algorithms

AlgorithmAverageWorstIn-placeStable
Bucket SortO(n + k)O(n²)NoYes
Counting SortO(n + k)O(n + k)NoYes
Radix SortO(nk)O(nk)NoYes
Merge SortO(n log n)O(n log n)NoYes
Quick SortO(n log n)O(n²)YesNo

For production use, Java's Arrays.sort() uses dual-pivot quicksort for primitives and Timsort for objects — both highly optimized. Implement bucket sort when you have a measured bottleneck and know your data distribution is uniform.

IntSummaryStatistics is a Java utility class that computes five statistics about a set of integers in a single pass: count, sum, min, max, and average. It's part of java.util and works naturally with Java 8 streams.

Instead of writing separate reductions for each statistic, summaryStatistics() gives you all five at once.


Getting IntSummaryStatistics from a Stream

import java.util.IntSummaryStatistics;
import java.util.stream.Stream;

public class IntSummaryStatisticsExample {

    public static void main(String[] args) {
        Stream<Integer> numStream = Stream.of(1, 2, 3, 4, 5);

        IntSummaryStatistics stats = numStream
                .mapToInt(Integer::intValue)
                .summaryStatistics();

        System.out.println("Count:   " + stats.getCount());   // 5
        System.out.println("Sum:     " + stats.getSum());     // 15
        System.out.println("Min:     " + stats.getMin());     // 1
        System.out.println("Max:     " + stats.getMax());     // 5
        System.out.println("Average: " + stats.getAverage()); // 3.0
    }
}

Output:

Count:   5
Sum:     15
Min:     1
Max:     5
Average: 3.0

Adding More Values with accept()

IntSummaryStatistics is mutable — you can continue feeding it new values after the initial stream:

IntSummaryStatistics stats = Stream.of(1, 2, 3, 4, 5)
        .mapToInt(Integer::intValue)
        .summaryStatistics();

// Add a new value after the stream is consumed
stats.accept(10);

System.out.println("Count:   " + stats.getCount());   // 6
System.out.println("Sum:     " + stats.getSum());     // 25
System.out.println("Min:     " + stats.getMin());     // 1
System.out.println("Max:     " + stats.getMax());     // 10
System.out.println("Average: " + stats.getAverage()); // 4.166...

Using with an IntStream Directly

When you already have an IntStream (e.g., from an int[] array), you don't need mapToInt():

import java.util.Arrays;

int[] values = {10, 20, 30, 40, 50};

IntSummaryStatistics stats = Arrays.stream(values).summaryStatistics();

System.out.println(stats);
// IntSummaryStatistics{count=5, sum=150, min=10, average=30.000000, max=50}

Using collect() for Custom Aggregation

You can also use Collectors.summarizingInt() when collecting from an object stream:

import java.util.List;
import java.util.stream.Collectors;

List<String> words = List.of("apple", "fig", "banana", "kiwi");

IntSummaryStatistics lengthStats = words.stream()
        .collect(Collectors.summarizingInt(String::length));

System.out.println("Shortest word length: " + lengthStats.getMin()); // 3
System.out.println("Longest word length:  " + lengthStats.getMax()); // 6
System.out.println("Average word length:  " + lengthStats.getAverage()); // 4.75

Available Methods

MethodReturn TypeDescription
getCount()longNumber of values
getSum()longSum of all values
getMin()intMinimum value
getMax()intMaximum value
getAverage()doubleArithmetic mean
accept(int)voidAdd a single value
combine(other)voidMerge another statistics object

Merging Two Statistics Objects with combine()

combine() merges a second IntSummaryStatistics into the current one, updating all five fields atomically:

IntSummaryStatistics batch1 = Stream.of(1, 2, 3)
        .mapToInt(Integer::intValue).summaryStatistics();

IntSummaryStatistics batch2 = Stream.of(4, 5, 6)
        .mapToInt(Integer::intValue).summaryStatistics();

batch1.combine(batch2);

System.out.println("Count:   " + batch1.getCount());   // 6
System.out.println("Sum:     " + batch1.getSum());     // 21
System.out.println("Min:     " + batch1.getMin());     // 1
System.out.println("Max:     " + batch1.getMax());     // 6
System.out.println("Average: " + batch1.getAverage()); // 3.5

This is useful when you're processing data in batches — compute statistics per batch, then merge them all at the end.


Using with Parallel Streams

summaryStatistics() is safe to use with parallel streams. The stream framework handles merging partial results from each thread using the combine() method internally:

IntSummaryStatistics parallelStats = IntStream.range(1, 1_000_001)
        .parallel()
        .summaryStatistics();

System.out.println("Sum: " + parallelStats.getSum());   // 500000500000
System.out.println("Max: " + parallelStats.getMax());   // 1000000

You get the same result as a sequential stream — parallelism is handled transparently.


LongSummaryStatistics and DoubleSummaryStatistics

Java provides equivalent classes for the other primitive numeric types:

ClassStream typegetSum() returns
IntSummaryStatisticsIntStreamlong
LongSummaryStatisticsLongStreamlong
DoubleSummaryStatisticsDoubleStreamdouble
// LongSummaryStatistics — for large numbers that overflow int
LongSummaryStatistics longStats = LongStream.of(1_000_000L, 2_000_000L, 3_000_000L)
        .summaryStatistics();
System.out.println("Sum: " + longStats.getSum());  // 6000000

// DoubleSummaryStatistics — for floating-point values
DoubleSummaryStatistics priceStats = DoubleStream.of(9.99, 24.50, 4.99)
        .summaryStatistics();
System.out.println("Avg price: $" + priceStats.getAverage()); // $13.16

Note that IntSummaryStatistics.getSum() returns long even though the inputs are int — this prevents overflow when summing many large integers.


Real-World Example: Analyzing Order Totals

import java.util.*;
import java.util.stream.*;

List<Integer> orderTotals = Arrays.asList(
    120, 45, 380, 95, 210, 67, 430, 28, 150, 300
);

IntSummaryStatistics stats = orderTotals.stream()
        .mapToInt(Integer::intValue)
        .summaryStatistics();

System.out.println("Orders:  " + stats.getCount());
System.out.println("Revenue: $" + stats.getSum());
System.out.println("Lowest:  $" + stats.getMin());
System.out.println("Highest: $" + stats.getMax());
System.out.printf("Average: $%.2f%n", stats.getAverage());
// Orders:  10
// Revenue: $1825
// Lowest:  $28
// Highest: $430
// Average: $182.50

Summary

IntSummaryStatistics is a clean, one-pass solution for computing common numeric statistics. Use it whenever you need more than one statistic from the same dataset — it's faster and cleaner than running separate stream operations. For large integers, use LongSummaryStatistics; for decimals, use DoubleSummaryStatistics.


Converting a Stream to a List is one of the most common stream operations. There are several ways to do it depending on your Java version and whether you need a mutable list.


Method 1: collect(Collectors.toList()) — Java 8+

The classic approach using the collect() terminal operation:

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
List<Integer> list = stream.collect(Collectors.toList());

System.out.println(list); // [1, 2, 3, 4, 5]

This returns a mutable ArrayList. You can add or remove elements from the result.


Method 2: Stream.toList() — Java 16+

Java 16 introduced a shorter, built-in method:

List<Integer> list = Stream.of(1, 2, 3, 4, 5).toList();
System.out.println(list); // [1, 2, 3, 4, 5]
Important: Stream.toList() returns an unmodifiable list. Trying to add or remove elements will throw UnsupportedOperationException. Use this when you don't need to mutate the result.

Method 3: collect(Collectors.toUnmodifiableList()) — Java 10+

If you want an unmodifiable list but are on Java 10–15:

List<Integer> list = Stream.of(1, 2, 3, 4, 5)
        .collect(Collectors.toUnmodifiableList());

Method 4: Collecting to a Specific List Type

If you need a specific List implementation (e.g., LinkedList):

import java.util.LinkedList;
import java.util.stream.Collectors;

List<Integer> linkedList = Stream.of(1, 2, 3, 4, 5)
        .collect(Collectors.toCollection(LinkedList::new));

Common Pattern: Filter, Transform, Collect

The real power shows when you chain operations before collecting:

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

List<String> names = Stream.of("alice", "bob", "charlie", "dave", "eve")
        .filter(name -> name.length() > 3)
        .map(String::toUpperCase)
        .collect(Collectors.toList());

System.out.println(names); // [ALICE, CHARLIE, DAVE]

Which Method to Use?

MethodJava VersionMutable?Notes
collect(Collectors.toList())8+YesMost common, returns ArrayList
Stream.toList()16+NoShortest syntax
collect(Collectors.toUnmodifiableList())10+NoExplicit about immutability
collect(Collectors.toCollection(...))8+YesWhen you need a specific type

For most cases on Java 16+, prefer Stream.toList() for its conciseness. On Java 8–15, use collect(Collectors.toList()).


Converting IntStream / LongStream to List

Primitive streams (IntStream, LongStream, DoubleStream) can't collect directly to List<Integer>. Use boxed() first to convert each primitive to its wrapper type:

// IntStream to List<Integer>
List<Integer> intList = IntStream.range(1, 6)
        .boxed()
        .collect(Collectors.toList());

System.out.println(intList); // [1, 2, 3, 4, 5]

// LongStream to List<Long>
List<Long> longList = LongStream.of(100L, 200L, 300L)
        .boxed()
        .collect(Collectors.toList());

// int[] array to List<Integer>
int[] arr = {10, 20, 30};
List<Integer> fromArray = Arrays.stream(arr)
        .boxed()
        .collect(Collectors.toList());

The boxed() call is required because List is a generic type and can't hold primitive int — only reference type Integer.


Collecting to Set and Map

The same pattern works for other collection types:

// Collect to a Set (deduplication)
Set<String> uniqueNames = Stream.of("alice", "bob", "alice", "charlie")
        .collect(Collectors.toSet());

// Collect to a Map (key = string, value = its length)
Map<String, Integer> nameLengths = Stream.of("alice", "bob", "charlie")
        .collect(Collectors.toMap(
            name -> name,           // key function
            String::length          // value function
        ));

Handling Null Elements

Both Collectors.toList() and Stream.toList() accept null elements in the stream. However, Stream.toList()'s unmodifiable list permits null values, while Collectors.toUnmodifiableList() throws a NullPointerException if the stream contains nulls:

Stream<String> withNull = Stream.of("a", null, "b");

// Works fine — ArrayList allows null
List<String> mutable = withNull.collect(Collectors.toList());

// Works fine — Stream.toList() allows null
Stream<String> withNull2 = Stream.of("a", null, "b");
List<String> immutable = withNull2.toList();

// Throws NullPointerException!
Stream<String> withNull3 = Stream.of("a", null, "b");
List<String> noNull = withNull3.collect(Collectors.toUnmodifiableList());

If your stream may contain nulls and you want an unmodifiable list, use Stream.toList() rather than Collectors.toUnmodifiableList().


Summary

collect(Collectors.toList()) is the standard way to convert a Stream to a List. On Java 16+, Stream.toList() is cleaner and should be your default when you don't need to mutate the result. For primitive streams (IntStream, etc.), call boxed() before collecting. Watch out for null handling differences between the unmodifiable collectors.

What Is a WAR File?

A WAR is a ZIP file with a specific directory structure. It contains:

  • WEB-INF/web.xml — the deployment descriptor (servlet mappings, listeners, filters)
  • WEB-INF/classes/ — compiled Java .class files
  • WEB-INF/lib/ — all dependency JARs bundled into the app
  • META-INF/MANIFEST.MF — archive metadata
  • Static resources (HTML, CSS, JS, images) in the root or subdirectories

The WEB-INF/ directory is special: files inside it are never served directly to clients by the servlet container.


Method 1: List Contents Without Extracting

jar -tvf myapp.war

Flags: -t (table/list), -v (verbose), -f (filename). Pipe through grep to find specific files:

jar -tvf myapp.war | grep "web.xml"
jar -tvf myapp.war | grep "\.properties"
jar -tvf myapp.war | grep "spring"

Example output:

     0 Thu Nov 30 12:00:00 EST 2023 META-INF/
   106 Thu Nov 30 12:00:00 EST 2023 META-INF/MANIFEST.MF
     0 Thu Nov 30 12:00:00 EST 2023 WEB-INF/
   742 Thu Nov 30 12:00:00 EST 2023 WEB-INF/web.xml
  4096 Thu Nov 30 12:00:00 EST 2023 WEB-INF/classes/com/example/MyServlet.class
 12345 Thu Nov 30 12:00:00 EST 2023 WEB-INF/lib/spring-core-5.3.20.jar

Method 2: Extract Everything

jar -xvf myapp.war

To extract into a specific folder:

mkdir -p extracted/myapp
cd extracted/myapp
jar -xvf ../../myapp.war

Method 3: Extract a Single File

# Extract just web.xml
jar -xvf myapp.war WEB-INF/web.xml

# Extract a specific class file
jar -xvf myapp.war WEB-INF/classes/com/example/MyServlet.class

# Extract a properties file
jar -xvf myapp.war WEB-INF/classes/application.properties

Method 4: Use unzip

Since WAR files are ZIP archives, unzip works and is often faster for large files:

# List contents (no extraction)
unzip -l myapp.war

# Extract everything
unzip myapp.war -d extracted/

# Extract a single file
unzip myapp.war WEB-INF/web.xml

# Extract all .properties files
unzip myapp.war "WEB-INF/classes/*.properties" -d config/

Typical WAR File Structure

myapp.war
├── META-INF/
│   └── MANIFEST.MF
├── WEB-INF/
│   ├── web.xml              ← deployment descriptor
│   ├── classes/             ← compiled .class files
│   │   ├── com/example/MyServlet.class
│   │   └── application.properties
│   └── lib/                 ← dependency JARs
│       ├── spring-core.jar
│       └── hibernate-core.jar
├── index.html               ← publicly accessible
├── css/
└── js/
LocationBrowser-accessible?Purpose
Root (/)YesStatic files (HTML, CSS, JS, images)
WEB-INF/NoPrivate — config, compiled code, libs
WEB-INF/classes/NoCompiled Java classes and resources
WEB-INF/lib/NoBundled dependency JARs
META-INF/NoArchive metadata

How to Build a WAR File

With Maven — add <packaging>war</packaging> to your pom.xml, then:

mvn clean package
# WAR created at target/myapp.war

With Gradle — apply the war plugin in build.gradle, then:

./gradlew war
# WAR created at build/libs/myapp.war

Viewing Class File Contents

To inspect a .class file's bytecode (after extracting it):

# Show method signatures
javap WEB-INF/classes/com/example/MyServlet.class

# Show full bytecode disassembly
javap -c WEB-INF/classes/com/example/MyServlet.class

For human-readable source code, use a Java decompiler like CFR.


Platform Support

PlatformNotes
Linux / macOSjar is in $JAVA_HOME/bin, usually in PATH
WindowsSame command in CMD or PowerShell if JDK is in PATH
No JDKUse unzip, 7-Zip, WinRAR, or Mac's Archive Utility

Quick Reference

jar -tvf myapp.war                          # list contents
jar -tvf myapp.war | grep web.xml           # find a specific file
jar -xvf myapp.war                          # extract everything
jar -xvf myapp.war WEB-INF/web.xml          # extract one file
unzip -l myapp.war                          # list with unzip
unzip myapp.war -d output/                  # extract to a folder

computeIfPresent() is a Map method introduced in Java 8 that conditionally updates a value using a function — but only if the key already exists in the map. If the key is absent, nothing happens. It replaces the verbose containsKey() + put() pattern with a single, expressive call.


Method Signature

V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
  • key — the key to look up
  • remappingFunction — receives the key and current value; its return value becomes the new value
  • Returns — the new value if key was present; null if absent or function returned null
  • Side effect — if the function returns null, the entry is removed from the map

Basic Example

import java.util.HashMap;
import java.util.Map;

public class ComputeIfPresentExample {

    public static void main(String[] args) {
        Map<String, Integer> prices = new HashMap<>();
        prices.put("Sunglasses", 105);
        prices.put("Watch", 1501);
        prices.put("Wallet", 299);

        System.out.println("Before: " + prices);

        // "Watch" exists — price is doubled
        prices.computeIfPresent("Watch", (key, value) -> value * 2);

        // "Bag" doesn't exist — map is unchanged
        prices.computeIfPresent("Bag", (key, value) -> value * 2);

        System.out.println("After:  " + prices);
        // {Watch=3002, Sunglasses=105, Wallet=299}
    }
}

Output:

Before: {Watch=1501, Sunglasses=105, Wallet=299}
After:  {Watch=3002, Sunglasses=105, Wallet=299}

Removing an Entry by Returning null

If the remapping function returns null, the entry is deleted:

Map<String, Integer> stock = new HashMap<>();
stock.put("Apples", 10);
stock.put("Bananas", 5);
stock.put("Cherries", 20);

// Remove items with stock below 8
stock.computeIfPresent("Apples",   (k, v) -> v < 8 ? null : v);  // 10 >= 8, kept
stock.computeIfPresent("Bananas",  (k, v) -> v < 8 ? null : v);  // 5 < 8, removed
stock.computeIfPresent("Cherries", (k, v) -> v < 8 ? null : v);  // 20 >= 8, kept

System.out.println(stock);
// {Apples=10, Cherries=20}

Before vs. After Java 8

Old approach — three lines, two map lookups:

if (prices.containsKey("Watch")) {
    prices.put("Watch", prices.get("Watch") * 2);
}

Modern approach — one line, atomic:

prices.computeIfPresent("Watch", (k, v) -> v * 2);

Beyond being cleaner, the modern approach is also atomic on ConcurrentHashMap, which makes it correct under concurrent access — the old pattern is not.


Real-World Example: Updating a Frequency Map

Map<String, Integer> wordCount = new HashMap<>();
wordCount.put("java", 5);
wordCount.put("python", 3);
wordCount.put("kotlin", 7);

String[] wordsToUpdate = {"java", "rust", "python", "go"};

for (String word : wordsToUpdate) {
    wordCount.computeIfPresent(word, (k, v) -> v + 1);
}

System.out.println(wordCount);
// {java=6, python=4, kotlin=7} — "rust" and "go" were NOT added

Real-World Example: Applying a Selective Discount

Map<String, Double> cart = new HashMap<>();
cart.put("Laptop",   999.99);
cart.put("Mouse",     29.99);
cart.put("Keyboard",  79.99);
cart.put("Monitor",  349.99);

List<String> saleItems = List.of("Mouse", "Keyboard", "Headphones");

for (String item : saleItems) {
    // Apply 20% discount — "Headphones" not in cart, skipped
    cart.computeIfPresent(item, (k, v) -> Math.round(v * 0.8 * 100.0) / 100.0);
}

cart.forEach((item, price) ->
    System.out.printf("%-12s $%.2f%n", item, price));
// Laptop       $999.99
// Mouse        $23.99
// Keyboard     $63.99
// Monitor      $349.99

Thread-Safe Use with ConcurrentHashMap

computeIfPresent() is atomic on ConcurrentHashMap. The check and the update happen as a single operation — no other thread can modify the entry between them:

import java.util.concurrent.ConcurrentHashMap;

ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.put("counter", 0);

// Safe to call from multiple threads concurrently
concurrentMap.computeIfPresent("counter", (k, v) -> v + 1);

The old containsKey() + put() pattern is not thread-safe — another thread can insert or remove the key between your two calls.


Related Map Compute Methods

MethodWhen to Use
computeIfPresent(k, fn)Update an existing value; do nothing if key absent
computeIfAbsent(k, fn)Insert a new value; do nothing if key present
compute(k, fn)Always call fn; fn receives null if key absent
merge(k, v, fn)Combine a new value with an existing one, or insert if absent
put(k, v)Always set a value, regardless of whether key exists
putIfAbsent(k, v)Insert only if key absent; fixed value (no function)

Summary

Use computeIfPresent() when you need to update an existing map entry based on its current value, without the boilerplate of a containsKey() check. It's cleaner, more expressive, and thread-safe when used with ConcurrentHashMap.